2014-11-01 401 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方法