Java Hibernate生成器类的使用
我正在使用Struts 1、hibernate 3、spring 1重构一个旧的web应用程序(2006年) 我正在升级图书馆 我使用hibernate映射xml文件修改“ID”/“Primary key”行为,以便与任何实际数据库兼容Java Hibernate生成器类的使用,java,hibernate,Java,Hibernate,我正在使用Struts 1、hibernate 3、spring 1重构一个旧的web应用程序(2006年) 我正在升级图书馆 我使用hibernate映射xml文件修改“ID”/“Primary key”行为,以便与任何实际数据库兼容 <class name="com...declaration.Declaration" table="DECLARATION"> <id name="pk" type="integer" column="PK_DECLARATI
<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>
据说我使用:
<class name="com....Declaration" table="DECLARATION">
<id name="pk" type="integer" column="PK_DECLARATION" unsaved-value="null">
<generator class="native"/>
....
....
现在我正在使用SQL Server。但如果有一天我必须更改(例如更改为Oracle),我是否必须更改所有映射才能兼容
问题是设置与多个数据库兼容的映射,最好的方法是使用“本机”生成器或创建我自己的?谢谢您的回答。因此,我的选择是设置我自己的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>
调用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);
}
公共类PkGenerator实现IdentifierGenerator,可配置{
公共静态最终字符串ID\u TABLE=“TABLE”;
公共静态最终字符串PK\u COLUMN\u NAME=“primary\u key\u COLUMN”;
公共静态最终字符串PK\u VALUE\u NAME=“primary\u key\u VALUE”;
公共静态最终字符串VALUE\u COLUMN\u NAME=“VALUE\u COLUMN”;
公共静态最终字符串PK\u LENGTH\u NAME=“primary\u key\u LENGTH”;
公共静态最终整数默认值为64;
票价
公共静态最终字符串默认值\u TABLE=“SEQUENCE”;
私有静态最终字符串DEFAULT\u PK\u COLUMN=“SEQUENCE\u NAME”;
私有静态最终字符串默认值\u COLUMN=“序列\u下一个\u值”;
//记忆
私有字符串表名;
私有字符串名称;
私有字符串pkValueName;
私有字符串valueColumnName;
私有字符串查询;
私有字符串插入;
私有字符串更新;
私有int密钥大小;
...
@凌驾
public void configure(类型、属性参数、方言)引发MappingException{
this.tableName=params.getProperty(ID_TABLE,默认_TABLE);
this.pkColumnName=params.getProperty(PK_COLUMN_NAME,默认值_PK_COLUMN);
this.pkValueName=params.getProperty(PK_VALUE_NAME);
this.valueColumnName=params.getProperty(值\列\名称,默认值\列);
this.keySize=ConfigurationHelper.getInt(主键长度名称、参数、默认主键长度);
//从带有(updlock,rowlock)的序列中选择数字,其中ENTITE=''
this.query=“从”+方言.appendLockHint(LockOptions.UPGRADE,this.tableName)中选择“+this.valueColumnName+”
+其中“+this.pkColumnName+”='”+this.pkValueName+“'”+方言.getForUpdateString();
//更新序列集NUMERO=?其中ENTITE=“”
this.update=“update”+this.tableName+“set”+this.valueColumnName+“=?”
+其中“+this.pkColumnName+”='”+this.pkValueName+“'”;
//插入序列(ENTITE,NUMERO)值('keyValue',?)
this.insert=“插入到“+tableName+”(“+pkColumnName+”,“+valueColumnName+”)中”
+“值”(“+”键值“+”,?)”;
}
...
@凌驾
public Serializable generate(SessionImplementor会话,Object obj)抛出HibernateeException{
/*session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
新org.hibernate.jdbc.AbstractWork(){
@凌驾
public void execute(连接)引发SQLException{
//在这里做你的工作,知道你是在一个新的交易
字符串tot=“”;
}
}
符合事实的
);
*/
Connection=session.Connection();
整数pk=null;
试一试{
PreparedStatement selectStatement=connection.prepareStatement(this.query);
ResultSet ResultSet=selectStatement.executeQuery();
//序列存在
if(resultSet.next()){
pk=resultSet.getInt(“NUMERO”);
}否则{
//序列不存在:创建它(插入)
pk=0;
PreparedStatement insertStatement=connection.prepareStatement(this.insert);
布尔ok=insertStatement.execute();
}
//序列更新
pk=pk+1;
PreparedStatement updateStatement=connection.prepareStatement(this.update);
setInt(1,pk.intValue());
updateStatement.executeUpdate();
字符串toto=“”;
}捕获(SQLE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(例外e){
e、 printStackTrace();
}
返回新的整数(pk);
}
通过“可配置”接口的实现,每个实例生成器将设置成员(表、名称、列等)以获取序列值。对象存储还将选择、插入和更新请求,以便获取最后一个索引、更新它、创建它(如果不存在)
现在我只是想知道,如果我设置了另一个(独立的)事务,我是否会在生成方法中执行select、update、insert。如果我在select(插入/更新之前)设置了数据库锁。参考说明:“它根据数据库选择标识、序列或hilo。“因此,这取决于它是否对您有效。如果我的第一个数据库是SQL Server(identity),如果我需要使用Oracle,我是否必须更改所有映射才能设置序列名称,并在数据库的每个表上创建序列?不幸的是,是的。在数据库中,您必须执行它所要求的任何操作,并且您必须更改映射。