Trying to persist object to Oracle with null value at nvarchar2 type
column causes
Caused by: <openjpa-2.0.1-r422266:989424 fatal general error>
org.apache.openjpa.persistence.PersistenceException: недействительный шаблон
имени: CHES.NVARCHAR2
FailedObject: prepstmnt 1108543980
INSERT INTO CHES.BAL_ENET_DATA (ID, GUID, NAME,
IS_SUBSTATION, IS_CONNECTION, IS_SECTION, TYPEID,
EQ_VOLTAGEID, EQ_SUBSTATIONID, EQ_SUBTYPEID3,
OWNID, EXPLOID, SUB_REGIONID, INVID, REG_ENPLANTID,
SNAPSHOT_DATE, SNAPSHOT_COUNT, PERIOD,
EQ_LINEOWNERID, EQ_LINEBEGINID, EQ_LINEENDID,
DELETED, NEED_SYNCH, EQ_SECTIONNUM,
EQ_GRANDPARENTID, EQ_SUBTYPEID1, IS_CONSUMER,
IS_OTHERRES, IS_MV2_INPUT, MANUAL_CONFIG,
IS_FROMOTPAIKA, OTPAIKANAME)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[org.apache.openjpa.jdbc.kernel.JDBCStoreManager$CancelPreparedStatement_]
at
org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4832)
at
org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4792)
at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:136)
at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:78)
at
org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushBatch(BatchingPreparedStatementManagerImpl.java:222)
at
org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:63)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:103)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:76)
at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731)
at
org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
... 42 more
Caused by: java.sql.SQLException: недействительный шаблон имени: CHES.NVARCHAR2
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at
oracle.jdbc.oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:463)
at oracle.jdbc.oracore.OracleTypeADT.init(OracleTypeADT.java:362)
at oracle.sql.StructDescriptor.initPickler(StructDescriptor.java:319)
at oracle.sql.StructDescriptor.<init>(StructDescriptor.java:283)
at
oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:194)
at
oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:163)
at
oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:132)
at
oracle.jdbc.driver.OraclePreparedStatement.setNullCritial(OraclePreparedStatement.java:4180)
at
oracle.jdbc.driver.OraclePreparedStatement.setNullInternal(OraclePreparedStatement.java:4143)
at
oracle.jdbc.driver.OraclePreparedStatement.setNull(OraclePreparedStatement.java:4122)
at
com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setNull(NewProxyPreparedStatement.java:183)
at
org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.setNull(DelegatingPreparedStatement.java:426)
at
org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.setNull(LoggingConnectionDecorator.java:1393)
at
org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.setNull(DelegatingPreparedStatement.java:426)
at
org.apache.openjpa.jdbc.sql.OracleDictionary.setNull(OracleDictionary.java:559)
at
org.apache.openjpa.jdbc.sql.DBDictionary.setTyped(DBDictionary.java:1221)
at org.apache.openjpa.jdbc.sql.RowImpl.flush(RowImpl.java:896)
at org.apache.openjpa.jdbc.sql.RowImpl.flush(RowImpl.java:856)
at
org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushBatch(BatchingPreparedStatementManagerImpl.java:168)
... 47 more
Overriding setNull() in OracleDictionary and using that overrided
dictionary solves problem for me.
public class OracleDictionary extends
org.apache.openjpa.jdbc.sql.OracleDictionary
{
@Override
public void setNull(PreparedStatement stmnt, int idx, int colType,
Column col) throws SQLException
{
if
(col.getTypeIdentifier().getName().toUpperCase().equals("NVARCHAR2"))
{
stmnt.setNull(idx, Types.VARCHAR);
}
else
{
super.setNull(stmnt, idx, colType, col);
}
}
}
But I think that should work without that hack out of the box.
Column type of NVARCHAR2 in standart Oracle dictionary determined as
java.sql.Type.OTHER and causes described problem.