2015-04-24 67 views
0

我正在重构旧的Web应用程序(2006)使用,Struts 1,休眠3,春天1 ...休眠生成器类的用法

我升级库。

使用Hibernate映射XML文件,我修改“ID” /主键”的行为,以便与任何实际的数据库兼容

我说要用:

<class name="com....Declaration" table="DECLARATION"> 
     <id name="pk" type="integer" column="PK_DECLARATION" unsaved-value="null"> 
      <generator class="native"/> 
      .... 

现在我但如果有一天我必须改变为例如甲骨文,我将不得不改变我的所有映射,以便兼容?

问题是设置映射兼容多个数据库,最好的方法是使用“本机”发电机或创建我自己的?

+0

参考文献说:“它根据数据库选择身份,序列或hilo。”所以这取决于它对你有效。 –

+0

如果我的第一个数据库是SQL Server(标识),并且如果需要使用Oracle,是否必须更改所有映射以设置序列名称,并在数据库的每个表上创建序列? – Anthony

+0

不幸的是,是的。在数据库中,你将不得不做任何需要的事情,你将不得不改变映射。 –

回答

0

感谢您的回答。所以我的选择将设置我自己的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); 
} 

随着“可配置”接口的实现,每个实例化的生成器将设置成员(表,名称,列,..)以获取序列值。对象存储也会选择,插入和更新请求以获取最后的索引,更新它,如果不存在则创建它。

现在我只是想知道如果我执行选择,更新,插入生成方法,如果我设置另一个(孤立的)事务。如果我选择(插入/更新之前)在数据库上设置锁定