/** Initialize the SEQUENCE key generator. */ public SequenceKeyGenerator(PersistenceFactory factory, Properties params, int sqlType) throws MappingException { boolean returning; _factoryName = factory.getFactoryName(); returning = "true".equals(params.getProperty("returning")); _triggerPresent = "true".equals(params.getProperty("trigger", "false")); if (!_factoryName.equals(OracleFactory.FACTORY_NAME) && !_factoryName.equals(PostgreSQLFactory.FACTORY_NAME) && !_factoryName.equals(InterbaseFactory.FACTORY_NAME) && !_factoryName.equals("sapdb") && !_factoryName.equals(DB2Factory.FACTORY_NAME)) { throw new MappingException( Messages.format("mapping.keyGenNotCompatible", getClass().getName(), _factoryName)); } if (!_factoryName.equals(OracleFactory.FACTORY_NAME) && returning) { throw new MappingException( Messages.format( "mapping.keyGenParamNotCompat", "returning=\"true\"", getClass().getName(), _factoryName)); } _factory = factory; _seqName = params.getProperty("sequence", "{0}_seq"); _style = (_factoryName.equals(PostgreSQLFactory.FACTORY_NAME) || _factoryName.equals(InterbaseFactory.FACTORY_NAME) || _factoryName.equals(DB2Factory.FACTORY_NAME) ? BEFORE_INSERT : (returning ? DURING_INSERT : AFTER_INSERT)); if (_triggerPresent && !returning) { _style = AFTER_INSERT; } if (_triggerPresent && _style == BEFORE_INSERT) throw new MappingException( Messages.format( "mapping.keyGenParamNotCompat", "trigger=\"true\"", getClass().getName(), _factoryName)); _sqlType = sqlType; supportsSqlType(sqlType); try { _increment = Integer.parseInt(params.getProperty("increment", "1")); } catch (NumberFormatException nfe) { _increment = 1; } }
/** * @param conn An open connection within the given transaction * @param tableName The table name * @param primKeyName The primary key name * @param props A temporary replacement for Principal object * @return A new key * @throws PersistenceException An error occured talking to persistent storage */ public Object generateKey(Connection conn, String tableName, String primKeyName, Properties props) throws PersistenceException { PreparedStatement stmt = null; ResultSet rs; String seqName; String table; seqName = MessageFormat.format( _seqName, new String[] {tableName, primKeyName}); // due to varargs in 1.5, see CASTOR-1097 table = _factory.quoteName(tableName); try { if (_factory.getFactoryName().equals(InterbaseFactory.FACTORY_NAME)) { // interbase only does before_insert, and does it its own way stmt = conn.prepareStatement( "SELECT gen_id(" + seqName + "," + _increment + ") FROM rdb$database"); rs = stmt.executeQuery(); } else if (_factory.getFactoryName().equals(DB2Factory.FACTORY_NAME)) { stmt = conn.prepareStatement("SELECT nextval FOR " + seqName + " FROM SYSIBM.SYSDUMMY1"); rs = stmt.executeQuery(); } else { if (_style == BEFORE_INSERT) { stmt = conn.prepareStatement("SELECT nextval('" + seqName + "')"); rs = stmt.executeQuery(); } else if (_triggerPresent && _factoryName.equals(PostgreSQLFactory.FACTORY_NAME)) { Object insStmt = props.get("insertStatement"); Class psqlStmtClass = Class.forName("org.postgresql.Statement"); Method getInsertedOID = psqlStmtClass.getMethod("getInsertedOID", (Class[]) null); int insertedOID = ((Integer) getInsertedOID.invoke(insStmt, (Object[]) null)).intValue(); stmt = conn.prepareStatement( "SELECT " + _factory.quoteName(primKeyName) + " FROM " + table + " WHERE OID=?"); stmt.setInt(1, insertedOID); rs = stmt.executeQuery(); } else { stmt = conn.prepareStatement( "SELECT " + _factory.quoteName(seqName + ".currval") + " FROM " + table); rs = stmt.executeQuery(); } } if (!rs.next()) { throw new PersistenceException( Messages.format("persist.keyGenFailed", getClass().getName())); } Object resultKey = null; int resultValue = rs.getInt(1); String resultColName = rs.getMetaData().getColumnName(1); int resultColType = rs.getMetaData().getColumnType(1); if (LOG.isDebugEnabled()) { LOG.debug( "JDBC query returned value " + resultValue + " from column " + resultColName + "/" + resultColType); } if (_sqlType == Types.INTEGER) { resultKey = new Integer(resultValue); } else if (_sqlType == Types.BIGINT) { resultKey = new Long(resultValue); } else if (_sqlType == Types.CHAR || _sqlType == Types.VARCHAR) { resultKey = String.valueOf(resultValue); } else { resultKey = new BigDecimal(resultValue); } if (LOG.isDebugEnabled()) { if (resultKey != null) { LOG.debug( "Returning value " + resultKey + " of type " + resultKey.getClass().getName() + " as key."); } } return resultKey; } catch (Exception ex) { throw new PersistenceException( Messages.format("persist.keyGenSQL", getClass().getName(), ex.toString())); } finally { JDOUtils.closeStatement(stmt); } }