Spring Data JPA inserting instead of Update
Hi I am new to Spring Data JPA and I am wondering even though I pass the Id to the entity, the Spring data jpa is inserting instead of merge. I thought when I implement the Persistable interface and implement the two methods:
public Long getId();
public Boolean isNew();
It will automatically merge instead of persist.
I have an entity class called User like:
@Entity
@Table(name = "T_USER")
public class User implements Serializable, Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "USER_ID")
private Long id;
@Column(name = "CREATION_TIME", nullable = false)
private Date creationTime;
@Column(name = "FIRST_NAME", nullable = false)
private String firstName;
@Column(name = "LAST_NAME", nullable = false)
private String lastName;
@Column(name = "MODIFICATION_TIME", nullable = false)
private Date modificationTime;
And have another class
@Entity
@Table(name = "T_USER_ROLE")
public class UserRole implements Serializable, Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long roleId;
@Column(name = "ROLE_NAME")
private String userRole;
}
I have a custom repository called UserRepostory extending JpaReopistory. I am hitting the save for merge and persist as I see the implementation demonstrate that Spring Data Jpa uses above two methods to either update or insert.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
I have been trying to figure out but didn't get any clue. Maybe you guys can help.
Solution 1:
I ran into this issue, tried to implement Persistable
to no avail, and then looked into the Spring Data JPA source. I don't necessarily see this in your example code, but I have a @Version
field in my entity. If there is a @Version
field Spring Data will test that value to determine if the entity is new or not. If the @Version
field is not a primitive and is null then the entity is considered new.
This threw me for a long time in my tests because I was not setting the version field in my representation but only on the persisted entity. I also don't see this documented in the otherwise helpful Spring Data docs (which is another issue...).
Hope that helps someone!
Solution 2:
By default Spring Data JPA inspects the identifier property of the given entity. If the identifier property is null
, then the entity will be assumed as new, otherwise as not new. It's Id-Property inspection
Reference
If you are using Spring JPA with EntityManager
calling .merge()
will update your entity and .persist()
will insert.
@PersistenceContext
private EntityManager em;
@Override
@Transactional
public User save(User user) {
if (user.getId() == null) {
em.persist(user);
return user;
} else {
return em.merge(user);
}
}
There is no need to implement the Persistable
interface.