2014-11-01 60 views
1

我正在使用Oracle數據庫。我們看到在致電我們的服務方面經常失敗。當我看着日誌,我在桌子上看到以下例外java.sql.BatchUpdateException:ORA-00001:我們生成主鍵時的唯一約束

java.sql.BatchUpdateException:ORA-00001:唯一約束

我們實現了主鍵生成。

請找代碼

<class name="com.dvo.History" table="HISTORY" > 
     <id name="hiId" type="java.lang.Long"> 
      <column name="HI_ID" precision="22" scale="0" /> 
      <generator class="com.radiant.cisms.hibernate.generator.SequenceGenerator">  
       <param name="TABLE_NAME">HISTORY</param> 
      </generator> 
     </id> 

類文件

package com.generator; 

import java.io.Serializable; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.Properties; 

import org.apache.log4j.Logger; 
import org.hibernate.HibernateException; 
import org.hibernate.MappingException; 
import org.hibernate.dialect.Dialect; 
import org.hibernate.engine.SessionImplementor; 
import org.hibernate.id.Configurable; 
import org.hibernate.id.IdentifierGenerator; 
import org.hibernate.type.Type; 


public class SequenceGenerator implements IdentifierGenerator, Configurable { 


    private static Logger logger = Logger.getLogger(SequenceGenerator.class); 

    String tableName; 

    public void configure(Type arg0, Properties arg1, Dialect arg2)throws MappingException { 
     tableName = arg1.getProperty("TABLE_NAME"); 
    } 


    public Serializable generate(SessionImplementor arg0, Object arg1)throws HibernateException { 
     return getNextValue(arg0); 
    } 


    public Serializable getNextValue(SessionImplementor session){ 
     Long nextValue = null; 
     PreparedStatement preparedStatement = null; 
     ResultSet resultSet = null; 
     try{ 
      Connection connection = session.connection(); 
      preparedStatement = connection.prepareStatement("SELECT SEQ_GENERATOR_VALUE FROM SEQ_GENERATOR WHERE SEQ_GENERATOR_TABLE = ?"); 
      preparedStatement.setString(1, tableName); 
      resultSet = preparedStatement.executeQuery(); 
      while(resultSet.next()){ 
       nextValue = resultSet.getLong("SEQ_GENERATOR_VALUE"); 
      } 
      resultSet.close(); 
      preparedStatement.close(); 
      preparedStatement = connection.prepareStatement("UPDATE SEQ_GENERATOR SET SEQ_GENERATOR_VALUE = ? WHERE SEQ_GENERATOR_TABLE = ?"); 
      preparedStatement.setLong(1, nextValue+1); 
      preparedStatement.setString(2, tableName); 
      preparedStatement.executeUpdate(); 
     } catch(SQLException e){ 
      logger.debug(e.getMessage()); 
     } catch(Exception e){ 
      logger.debug(e.getMessage()); 
     } 
     finally{ 

      try{ 
       resultSet.close(); 
       preparedStatement.close(); 
      } catch(SQLException e){ 
       logger.debug(e.getMessage()); 
      } 
     } 
     return nextValue; 
    } 

} 

我們正在與甲骨文序列

+0

某處年底完成莫名其妙的主鍵不唯一。 – 2014-11-01 11:15:47

回答

0

添加同步到您的getNextValue方法替換該代碼。

synchronized public Serializable getNextValue(SessionImplementor session) 

測試並讓我知道結果應該工作。

+0

我們試過這個選項,但它不起作用 – MJS 2014-11-01 13:21:22

+0

它是一個網絡應用程序嗎? – jitsonfire 2014-11-01 13:22:53

+0

也請嘗試在prepareStatement.executeUpdate()後進行提交。 – jitsonfire 2014-11-01 13:25:16

0

您需要在從seq_generator表中選擇時創建排它鎖。

試試這個

preparedStatement = connection.prepareStatement("SELECT SEQ_GENERATOR_VALUE FROM SEQ_GENERATOR WHERE SEQ_GENERATOR_TABLE = ? FOR UPDATE"); 

當然,承諾必須在getNextValue方法