我使用的是由嵌入式内存数据库支持的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,其名称为“Tom”。我使用 findOne 方法检索记录,如下所示:
public Person getPersonById(long personId) {
Person person = personRepository.findOne(personId);
但是我原本期望第二次尝试因为一些PrimaryKey Constraint Violation而失败,名称没有从“Johan”更改为“Tom”。
问题:
P.S。:我有兴趣手动插入主键,因此 @GeneratedValue 或任何其他原则上无法传递两次相同键的机制都不是一种选择。
答案 0 :(得分:2)
如果你看一下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。
答案 1 :(得分:1)
在spring数据jpa中,当使用非自动生成的id保存无管理实体时,jpa将查找id,如果数据库中存在id,则会将save视为update,因此您只需更新记录< / p>