final Connection conn, final Identity identity, final ProposedEntity entity)
throws PersistenceException {
Identity internalIdentity = identity;
SQLEngine extended = _engine.getExtends();
if ((extended == null) && (internalIdentity == null)) {
throw new PersistenceException(Messages.format("persist.noIdentity", _type));
}
PreparedStatement stmt = null;
try {
// must create record in the parent table first. all other dependents
// are created afterwards. quick and very dirty hack to try to make
// multiple class on the same table work.
if (extended != null) {
ClassDescriptor extDesc = extended.getDescriptor();
if (!new ClassDescriptorJDONature(extDesc).getTableName().equals(_mapTo)) {
internalIdentity = extended.create(database, conn, entity, internalIdentity);
}
}
// we only need to care on JDBC 3.0 at after INSERT.
stmt = conn.prepareStatement(_statement);
if (LOG.isTraceEnabled()) {
LOG.trace(Messages.format("jdo.creating", _type, stmt.toString()));
}
SQLColumnInfo[] ids = _engine.getColumnInfoForIdentities();
if (internalIdentity.size() != ids.length) {
throw new PersistenceException("Size of identity field mismatched!");
}
// must remember that SQL column index is base one.
int count = 1;
for (int i = 0; i < ids.length; i++) {
stmt.setObject(count++, ids[i].toSQL(internalIdentity.get(i)));
}
if (LOG.isTraceEnabled()) {
LOG.trace(Messages.format("jdo.creating", _type, stmt.toString()));
}
count = bindFields(entity, stmt, count);
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.format("jdo.creating", _type, stmt.toString()));
}
stmt.executeUpdate();
stmt.close();
return internalIdentity;
} catch (SQLException except) {
LOG.fatal(Messages.format("jdo.storeFatal", _type, _statement), except);
Boolean isDupKey = _factory.isDuplicateKeyException(except);
if (Boolean.TRUE.equals(isDupKey)) {
throw new DuplicateIdentityException(Messages.format(
"persist.duplicateIdentity", _type, internalIdentity), except);
} else if (Boolean.FALSE.equals(isDupKey)) {
throw new PersistenceException(Messages.format("persist.nested", except), except);
}
// without an identity we can not check for duplicate key
if (internalIdentity == null) {
throw new PersistenceException(Messages.format("persist.nested", except), except);
}
// check for duplicate key the old fashioned way, after the INSERT
// failed to prevent race conditions and optimize INSERT times.
_lookupStatement.executeStatement(conn, internalIdentity);
try {
if (stmt != null) { stmt.close(); }
} catch (SQLException except2) {
LOG.warn("Problem closing JDBC statement", except2);
}
throw new PersistenceException(Messages.format("persist.nested", except), except);
}
}