简体   繁体   中英

java.sql.BatchUpdateException: ORA-00001: unique constraint while we generating primary key

I am using Oracle database. We are seeing frequent failures in calls to our service. When I looked at the logs I am seeing following exceptions on a table

java.sql.BatchUpdateException: ORA-00001: unique constraint

we implemented Primary key generation.

please find the code

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

class file

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

}

We are replacing this code with oracle sequence

Add synchronized to your getNextValue method.

 synchronized public Serializable getNextValue(SessionImplementor session)

Test and let me know the results should work.

You need to create an exclusive lock while select from seq_generator table.

Try this

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

and of course commit must be done at the end of getNextValue method

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM