Hibernate约束ConstraintViolationException。是否有一种简单的方法可以忽略重复的条目?

时间:2010-05-23 23:35:09

标签: java mysql hibernate

基本上我有以下架构,如果它们不存在我会插入记录。但是,当涉及到插入副本时,它会抛出错误,正如我所料。我的问题是,是否有一种简单的方法可以让Hibernate忽略实际插入重复项的插入?

CREATE TABLE IF NOT EXISTS `method` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;


SEVERE: Duplicate entry 'GET' for key 'name'
Exception in thread "pool-11-thread-4" org.hibernate.exception.ConstraintViolationException: could not insert:

8 个答案:

答案 0 :(得分:13)

  

我的问题是,是否有一种简单的方法可以让Hibernate忽略实际插入重复的插入?

如果没有实际插入记录,Hibernate怎么可能知道记录具有非唯一值?

如果您正在进行批量插入,并且不希望回滚整个事务并在ConstraintViolationException的情况下丢弃会话(这是您在异常后理论上应该做的事情,请参阅this thread这个previous answer),我的建议是使用StatelessSession API并抓住ConstraintViolationException

答案 1 :(得分:10)

Hibernate无法做到这一点。但是你可以自己做。基本上有两种选择:

  1. 插入前检查重复项;或
  2. 捕获ConstraintViolationException,然后确保违规是由于重复(因为可能有其他原因,如空字段)。
  3. 前者的缺点是,当实际存在重复的可能性较低时,您要检查每个插入的重复项。对于没有重复发生的通常情况,后者会更快,但缺点是您需要在面后检查重复项。抛出ConstraintViolationException时,它会使当前会话无效;这意味着您需要在搜索副本之前进行刷新。

    在插入之前检查重复项可能是最干净的方法,除非您需要担心一个主要的性能问题。确保执行查找并在事务中插入以确保某人不在查找和插入之间添加重复项,否则您将获得ConstraintViolationException。

答案 2 :(得分:1)

就像帕斯卡尔所说的那样,Hibernate不会知道它是否重复,直到它实际上已经被发现。

我之前遇到过类似的情况;几个线程正在对DB进行插入,但其中一些是重复的。我所做的只是在抛出其中一个异常时抓住并优雅地恢复。

答案 3 :(得分:1)

不使用hibernate中的createQuery(),而是使用createSQLQuery()并尝试查询“REPLACE INTO method(id)VALUES(123);”

答案 4 :(得分:1)

您可以尝试捕获异常org.hibernate.exception.ConstraintViolationException并在代码中吞下异常

例如:

try {
    sessionFactory.getCurrentSession().saveOrUpdate(entity);
} catch (ConstraintViolationException e) {
    // Ignore the exception here by doing nothing
}

答案 5 :(得分:1)

你可以在你的实体上使用@SqlInsert注释,改变sql hibernate用来在数据库中插入,hibernate目前必须使用这个语句

insert into method(name, id) values (?,?)

如果您使用的是mysql,可以使用@SqlInsert语句通过使用insert ignore mysql语句来更改insert sql

@SQLInsert(sql = "insert ignore into method(name, id) values (?,?)")

但是你应该通过在hibernate中启用show sql模式来获取插入sqls,因为列的顺序是通过一些逻辑生成的,并且他们的文档建议这样。

答案 6 :(得分:0)

这就是我解决此问题的方法:

try {
     session.save(object);
    }catch(JDBCException exception) {
        Throwable cause = exception.getCause();
        if(cause!=null && cause.getMessage().contains("Duplicate entry")){
            session.clear(); 
            throw new DuplicateEntityException("Duplicate entry");
        }else{
            throw exception; 
        }
    }

答案 7 :(得分:-1)

即使您发现异常,也可能存在其他问题

try{
       session.save(O);
       session.getTransaction().commit();
    }catch (HibernateException e) {
       System.out.println("you are carched ¤#%SD¤") ;
    }