Java Hibernate生成器类的使用

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

我正在使用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_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,我是否必须更改所有映射才能设置序列名称,并在数据库的每个表上创建序列?不幸的是,是的。在数据库中,您必须执行它所要求的任何操作,并且您必须更改映射。