【问题标题】:Enforcing primary key constraint in Spring JPA在 Spring JPA 中强制执行主键约束
【发布时间】:2017-11-30 09:30:38
【问题描述】:

我正在使用由嵌入式内存数据库支持的 Spring JPA,特别是 Apache Derby。

简单地说,我有一个这样的实体类:

@Entity
public class Person {

    @Id
    @NotNull
    @Column(unique = true, updatable = false, name = "PERSON_ID")
    private Long personId;

    @NotNull
    @Size(min = 1)
    private String name;

    public Person() {
    } 
    //continue....

在@Service 组件中,我有一个这样的方法:

@Autowired
private PersonRepository personRepository;

@Override
public void addPerson(Person person)  {
        personRepository.save(movie);
}

存储库定义如下:

public interface PersonRepository extends CrudRepository<Person, Long> { }

问题如下:主键约束没有像我预期的那样强制执行。

更具体地说,如果我有两个具有相同键的 Person 对象:

Person person1 = new Person(1L, "Johan");
Person person2 = new Person(1L, "Tom");

我依次调用add方法:

serviceObject.addPerson(person1);
serviceObject.addPerson(person2);

将会发生的是 personRepository.save(movie) 方法将保存一个具有相同 ID 的 Person 两次,从而覆盖之前的记录。最终只有一个具有该 ID 的 Person,其名称为“Tom”。我使用 findOne 方法检索记录,如下所示:

public Person getPersonById(long personId) {
    Person person = personRepository.findOne(personId);

但是我预计第二次尝试会因为违反 PrimaryKey 约束而失败,并且名称没有从“Johan”更改为“Tom”。

问题:

  • 为什么会这样?
  • 我知道我可以在数据库级别强制执行此规则。这是实现它的唯一方法吗?就我而言,使用 Apache Derby,我可以实现这一点吗?或者如何在 JPA 级别强制执行通常的主键约束,以便拒绝具有重复键的记录而不是覆盖之前的记录?

P.S.:我有兴趣手动插入主键,所以 @GeneratedValue 或任何其他原则上会阻止传递两次相同键的机制都不是一个选项。

【问题讨论】:

    标签: hibernate jpa spring-data spring-data-jpa derby


    【解决方案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);
        }
    }
    

    如果记录已经存在,它会尝试合并。在您的情况下,将主键的生成留给 spring 并在您的代码中使用生成的 id。

    【讨论】:

      【解决方案2】:

      在 spring data jpa 中,当使用非自动生成的 id 保存非托管实体时,jpa 将查找 id,如果 id 存在于数据库中,它将把保存视为更新,所以你只是在更新你的记录

      【讨论】:

      • 你所说的持久化上下文是指一个执行约束的真实数据库?
      • 那么实现它的唯一方法是将规则放在数据库级别?
      • 没有持久化上下文是像缓存一样的内存存储
      • 为什么你的id不是自动生成的?
      • 在这种情况下,您可以为用户添加和 Id 并为此设置唯一约束,但将 id 的生成留给 jpa。
      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 2011-09-07
      • 2019-01-09
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 2014-11-28
      • 2012-12-05
      相关资源
      最近更新 更多