|
|||||||||||
|
Re: [JDBC] Batch INSERT failing with error 22P02
From: Eric Faulhaber <ecf(at)goldencode.com>
Date: Thu Sep 20 2007 - 12:11:40 EDT
What in the log file is indicating the use of an unspecified type to you? I'd like to investigate this further. > Many thanks for a deep look into the log file and for a detailed description of what is going on. Your analysis has given me some great insight which has led to a possible solution (see below). Nevertheless, I'd still be interested to find out what triggered this change in behavior from version to version given my use case. > No. > Yes, this is caused by our implementation of custom Hibernate types. We map standard SQL types to custom Java data type wrappers due to specific runtime requirements. We leverage Hibernate's UserType facility for this, which requires that we implement the code to serialize Java data objects to and from JDBC via an instance of either PreparedStatement (to) or ResultSet (from) handed to us by Hibernate at the appropriate times. Note that our string columns are defined as text rather than character varying(n). This is because we don't know how wide the string data we will be expected to handle can be. Because the PG docs claim there is no performance disadvantage to using text vs. character varying, we go with text in all cases, thereby avoiding the headache of determining a max width for varchar columns. As a result, our custom user type for string data publishes its corresponding JDBC type as Types.CLOB. This was a somewhat arbitrary (and in retrospect, probably bad) decision, intended to match Hibernate's PostgreSQLDialect's mapping of Types.CLOB to PG's text type. In the code which serializes data to JDBC, we need to handle the possibility of the data being unknown at runtime. If the data is known, we use PreparedStatement.setString(index, "data"), which evidently uses Types.VARCHAR. If unknown, we instead use PreparedStatement.setNull(index, Types.CLOB). This explains why we sometimes get strings and sometimes Clobs, but where the unspecified type comes from, I have no idea. The only way data is imported is via the mechanism described above: a PreparedStatement INSERT which Hibernate generates, into which we set positional parameters. For this table, we would use only the following PreparedStatement methods:
setString(int, java.lang.String) --> for text data
setInt(int, int) --> for integer data
We never use setNull(x, Types.OTHER) nor setObject(x, null). Interestingly, if I publish either VARCHAR or LONGVARCHAR as the JDBC type associated with my custom user type for text, the problem no longer occurs. This effectively changes the second parameter in the PreparedStatement.setNull(int, int) call from CLOB to VARCHAR/LONGVARCHAR. I'll have to re-run the full import over the weekend to see if this has any repercussions with other tables. Also, I'll have to do a lot of regression testing of our runtime to see if this impacts anything else, as I'm not familiar enough with all the places Hibernate may use this information. > Each table is imported on a dedicated thread. So, despite the log message, only one thread was running in this case, since only one table was being imported. The second thread was never dispatched. Normally, we import a large number of tables, so the distribution of work is more efficient than in this case. So, no, Connection instances are never shared across threads.
Thanks,
---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to majordomo@postgresql.org so that your
message can get through to the mailing list cleanly
Received on Thu Sep 20 12:26:45 2007This archive was generated by hypermail 2.1.8 : Sun Oct 07 2007 - 12:19:53 EDT |
||||||||||
|
|||||||||||