感谢您的回答。所以我的选择将设置我自己的ID/PK生成器类,以避免更改我的映射,如果我更改数据库。
<class name="com...declaration.Declaration" table="DECLARATION">
<id name="pk" type="integer" column="PK_DECLARATION" unsaved-value="null">
<generator class="com....PkGenerator">
<param name="table">SEQUENCE</param>
<param name="primary_key_column">ENTITE</param>
<param name="primary_key_value">DECLARATION</param>
<param name="value_column">NUMERO</param>
</generator>
</id>
<timestamp name="version" column="DATE_VERSION" unsaved-value="null" />
<property name="dateDebutAdresseProvisoire" type="timestamp" column="DATE_DEBUT_ADRESSE_PROVISOIRE" />
....
</class>
1st我有一张名为SEQUENCE的表。该表存储在存储每个对象的最后一个ID(以法语抱歉一些变量:旧的代码)。
ENTITE NUMERO DATE DISCRIMINANT
---------------------------------------
DECLARATION 2 NULL NULL
....
当PK发生器类被调用时,最后一个ID被选中并且递增。如果ID不存在,则创建一个。
PK生成器类使用IdentifierGenerator,可配置接口。
public class PkGenerator implements IdentifierGenerator, Configurable {
public static final String ID_TABLE = "table";
public static final String PK_COLUMN_NAME = "primary_key_column";
public static final String PK_VALUE_NAME = "primary_key_value";
public static final String VALUE_COLUMN_NAME = "value_column";
public static final String PK_LENGTH_NAME = "primary_key_length";
public static final Integer DEFAULT_PK_LENGTH = 64;
// Valeurs par defaut
public static final String DEFAULT_TABLE = "SEQUENCE";
private static final String DEFAULT_PK_COLUMN = "SEQUENCE_NAME";
private static final String DEFAULT_VALUE_COLUMN = "SEQUENCE_NEXT_VALUE";
// Membres
private String tableName;
private String pkColumnName;
private String pkValueName;
private String valueColumnName;
private String query;
private String insert;
private String update;
private int keySize;
...
@Override
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
this.tableName = params.getProperty(ID_TABLE, DEFAULT_TABLE);
this.pkColumnName = params.getProperty(PK_COLUMN_NAME, DEFAULT_PK_COLUMN);
this.pkValueName = params.getProperty(PK_VALUE_NAME);
this.valueColumnName = params.getProperty(VALUE_COLUMN_NAME, DEFAULT_VALUE_COLUMN);
this.keySize = ConfigurationHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH);
// select NUMERO from SEQUENCE with (updlock, rowlock) where ENTITE = '<TABLE>'
this.query = "select " + this.valueColumnName + " from " + dialect.appendLockHint(LockOptions.UPGRADE, this.tableName)
+ " where " + this.pkColumnName + " = '" + this.pkValueName + "'" + dialect.getForUpdateString();
// update SEQUENCE set NUMERO = ? where ENTITE = '<TABLE>'
this.update = "update " + this.tableName + " set " + this.valueColumnName + " = ? "
+ "where " + this.pkColumnName + " = '" + this.pkValueName + "'";
// insert into SEQUENCE(ENTITE, NUMERO) values('keyValue', ?)
this.insert = "insert into " + tableName + "(" + pkColumnName + ", " + valueColumnName + ") "
+ "values('" + "keyValue" + "', ?)";
}
...
@Override
public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
/* session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
new org.hibernate.jdbc.AbstractWork() {
@Override
public void execute(Connection connection) throws SQLException {
// do your work here, knowing you are in a new transaction
String tot = "";
}
}
,true
);
*/
Connection connection = session.connection();
Integer pk = null;
try {
PreparedStatement selectStatement = connection.prepareStatement(this.query);
ResultSet resultSet = selectStatement.executeQuery();
// Sequence exists
if (resultSet.next()) {
pk = resultSet.getInt("NUMERO");
} else {
// Sequence does not exist : create it (insert)
pk = 0;
PreparedStatement insertStatement = connection.prepareStatement(this.insert);
Boolean ok = insertStatement.execute();
}
// Sequence update
pk = pk + 1;
PreparedStatement updateStatement = connection.prepareStatement(this.update);
updateStatement.setInt(1, pk.intValue());
updateStatement.executeUpdate();
String toto = "";
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return new Integer(pk);
}
随着“可配置”接口的实现,每个实例化的生成器将设置成员(表,名称,列,..)以获取序列值。对象存储也会选择,插入和更新请求以获取最后的索引,更新它,如果不存在则创建它。
现在我只是想知道如果我执行选择,更新,插入生成方法,如果我设置另一个(孤立的)事务。如果我选择(插入/更新之前)在数据库上设置锁定
参考文献说:“它根据数据库选择身份,序列或hilo。”所以这取决于它对你有效。 –
如果我的第一个数据库是SQL Server(标识),并且如果需要使用Oracle,是否必须更改所有映射以设置序列名称,并在数据库的每个表上创建序列? – Anthony
不幸的是,是的。在数据库中,你将不得不做任何需要的事情,你将不得不改变映射。 –