【问题标题】:Hibernate does not throw an exception on duplicate primary keyHibernate 不会在重复主键上抛出异常
【发布时间】:2018-10-04 16:08:43
【问题描述】:

我正在使用 Spring Data JPA。鉴于此设置:

@Entity
public class Role
{
    @Id
    @Column(nullable = false, unique = true)
    private String name;

    @Column
    private String info;
}

@Repository
public interface RoleRepository extends CrudRepository<Role, String>
{
}

我可以简单地插入具有相同主键 (name) 的 Role 两次。它只是更新数据库中的条目。我希望它抛出一个异常。尝试在数据库级别插入两个具有相同主键的条目会产生所需的“重复键”错误。


示例:

角色表为空

MariaDB [logz]> select * from role;
Empty set (0.00 sec)

第一次保存

roleRepository.save(new Role("name1", "info0"));

休眠先检查,再保存

Hibernate: select role0_.name as name1_3_0_, role0_.info as info2_3_0_ from role role0_ where role0_.name=?
Hibernate: insert into role (info, name) values (?, ?)

角色表已填写

MariaDB [logz]> select * from role;
+-------+-------+
| name  | info  |
+-------+-------+
| name1 | info0 |
+-------+-------+
1 row in set (0.00 sec)

第二次保存

roleRepository.save(new Role("name1", "info1"));

Hibernate 检查和更新 - 不过我想要一个例外!

Hibernate: select role0_.name as name1_3_0_, role0_.info as info2_3_0_ from role role0_ where role0_.name=?
Hibernate: update role set info=? where name=?

角色表已简单更新:(

MariaDB [logz]> select * from role;
+-------+-------+
| name  | info  |
+-------+-------+
| name1 | info1 |
+-------+-------+
1 row in set (0.00 sec)

【问题讨论】:

    标签: java hibernate jpa spring-data-jpa


    【解决方案1】:

    如果你看一下 save 方法的实现,它是这样的:

    @Transactional
    public <S extends T> S save(S entity) {
    
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }
    

    因此您可以注意到,如果具有特定 id 的对象已经存在于数据库中,它将进行更新。如果你更感兴趣,可以找到源here

    【讨论】:

    • 但是您对现在如何解决这个问题有什么建议吗?我的意思是,例如在创建用户时,我不会不小心将新用户“覆盖”(合并)到现有用户中。每次插入之前,我真的必须检查现有条目吗?
    • 您不应该手动生成 ID。就此而言,您甚至不应该将 String 用于 id 。您必须定义 ORM 提供者将用来分配 id 的策略(可能是序列)。
    • 但我想使用自然主键。那是错的吗?我应该只使用合成键并将我的列(之前是我的自然主键)标记为唯一吗?
    • @ImpulseTheFox 如果您自己处理密钥的唯一性,您可以做到,是的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    • 2016-08-27
    相关资源
    最近更新 更多