I am using Spring JPA backed by an embedded in-memory database, specifically Apache Derby.
Simply put, I have an entity class like this:
@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....
and in a @Service component I have a method like this:
@Autowired
private PersonRepository personRepository;
@Override
public void addPerson(Person person) {
personRepository.save(movie);
}
where the repository is defined as follows:
public interface PersonRepository extends CrudRepository<Person, Long> { }
The problem is the following: the primary key constraint is not enforced as I would expect.
More specifically, If I have two Person object with the same key:
Person person1 = new Person(1L, "Johan");
Person person2 = new Person(1L, "Tom");
and I call in sequence the add method:
serviceObject.addPerson(person1);
serviceObject.addPerson(person2);
what will happen is that the personRepository.save(movie) method is going to save a Person with same ID twice, thus overwriting the former record. In the end there is only one Person with that ID, and its name is "Tom". I retrieve a record using the findOne method as follows:
public Person getPersonById(long personId) {
Person person = personRepository.findOne(personId);
However I would have expected the second attempt to fail because of some PrimaryKey Constraint Violation, with the name not being changed from "Johan" to "Tom".
Questions:
P.S.: I am interested into inserting the primary key manually, so @GeneratedValue or any other mechanism that would prevent in principle to pass twice the same key are not an option.
If you look at the implementation on save method,
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
it is trying to merge if the record already exists. In your case leave the generation of primary key to spring and use the generated id in your code.