if ( _keyGen == null || _keyGen.getStyle() == KeyGenerator.BEFORE_INSERT ) {
if ( _ids.length > 1 && !(identity instanceof Complex) )
throw new PersistenceException( "Multiple identities expected!" );
if ( identity instanceof Complex ) {
Complex id = (Complex) identity;
if ( id.size() != _ids.length || _ids.length <= 1 )
throw new PersistenceException( "Size of complex field mismatched!");
for ( int i=0; i<_ids.length; i++ )
stmt.setObject( count++, idToSQL( i, id.get(i) ) );
} else {
if ( _ids.length != 1 )
throw new PersistenceException( "Complex field expected!" );
stmt.setObject( count++, idToSQL( 0, identity ) );
}
}
for ( int i = 0 ; i < _fields.length ; ++i ) {
if ( _fields[ i ].store ) {
if ( fields[i] == null ) {
for ( int j=0; j < _fields[i].columns.length; j++ )
stmt.setNull( count++, _fields[i].columns[j].sqlType );
} else if ( fields[i] instanceof Complex ) {
Complex complex = (Complex)fields[i];
if ( complex.size() != _fields[i].columns.length )
throw new PersistenceException( "Size of complex field mismatch!" );
for ( int j=0; j<_fields[i].columns.length; j++ ) {
Object value = ( complex == null ? null : complex.get(j) );
SQLTypes.setObject( stmt, count++, toSQL( i, j, value), _fields[i].columns[j].sqlType );
}
} else {
if ( _fields[i].columns.length != 1 )
throw new PersistenceException( "Complex field expected! ");
SQLTypes.setObject( stmt, count++, toSQL( i, 0, fields[i]), _fields[i].columns[0].sqlType );
}
}
}
// Generate key during INSERT
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.DURING_INSERT ) {
CallableStatement cstmt = (CallableStatement) stmt;
int sqlType;
sqlType = _ids[0].sqlType;
cstmt.registerOutParameter( count, sqlType );
cstmt.execute();
// First skip all results "for maximum portability"
// as proposed in CallableStatement javadocs.
while ( cstmt.getMoreResults() || cstmt.getUpdateCount() != -1 );
// Identity is returned in the last parameter
// Workaround: for INTEGER type in Oracle getObject returns BigDecimal
if ( sqlType == java.sql.Types.INTEGER )
identity = new Integer( cstmt.getInt( count ) );
else
identity = cstmt.getObject( count );
identity = idToJava( 0, identity );
} else
stmt.executeUpdate();
stmt.close();
// Generate key after INSERT
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.AFTER_INSERT ) {
identity = generateKey( database, conn, stmt );
}
return identity;
} catch ( SQLException except ) {
if ( _logInterceptor != null )
_logInterceptor.storeStatement( "Error creating " + _type + ", SQL : " + _sqlCreate );
// [oleg] Check for duplicate key based on X/Open error code
// Bad way: all validation exceptions are reported as DuplicateKey
//if ( except.getSQLState() != null &&
// except.getSQLState().startsWith( "23" ) )
// throw new DuplicateIdentityException( _clsDesc.getJavaClass(), identity );
// Good way: let PersistenceFactory try to determine
Boolean isDupKey;
isDupKey = _factory.isDuplicateKeyException( except );
if ( Boolean.TRUE.equals( isDupKey ) ) {
throw new DuplicateIdentityException( Messages.format("persist.duplicateIdentity", _clsDesc.getJavaClass().getName(), identity ) );
} else if ( Boolean.FALSE.equals( isDupKey ) ) {
throw new PersistenceException( Messages.format("persist.nested", except), except );
}
// else unknown, let's check directly.
// [oleg] Check for duplicate key the old fashioned way,
// after the INSERT failed to prevent race conditions
// and optimize INSERT times
try {
// Close the insert statement
if ( stmt != null )
stmt.close();
stmt = ( (Connection) conn ).prepareStatement( _pkLookup );
if (_logger != null) _logger.println(_pkLookup);
// bind the identity to the preparedStatement
count = 1;
if ( identity instanceof Complex ) {
Complex id = (Complex) identity;
if ( id.size() != _ids.length || _ids.length <= 1 )
throw new PersistenceException( "Size of complex field mismatched!");
for ( int i=0; i<_ids.length; i++ )
stmt.setObject( count++, idToSQL( i, id.get(i) ) );
} else {
if ( _ids.length != 1 )
throw new PersistenceException( "Complex field expected!" );