【问题标题】:java.sql.BatchUpdateException: ORA-00001: unique constraint while we generating primary keyjava.sql.BatchUpdateException:ORA-00001:我们生成主键时的唯一约束
【发布时间】:2014-12-28 14:30:18
【问题描述】:

我正在使用 Oracle 数据库。我们在调用我们的服务时经常看到失败。当我查看日志时,我在表上看到以下异常

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;
    }

}

我们正在用 oracle 序列替换这段代码

【问题讨论】:

  • 某处主键不是唯一的。

标签: java sql hibernate jdbc


【解决方案1】:

将同步添加到您的 getNextValue 方法。

 synchronized public Serializable getNextValue(SessionImplementor session)

测试并告诉我结果应该有效。

【讨论】:

  • 也尝试在preparedStatement.executeUpdate()之后提交;
【解决方案2】:

您需要在从 seq_generator 表中选择时创建一个排他锁。

试试这个

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

当然提交必须在 getNextValue 方法结束时完成

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多