I found a strange phenomenon while testing the mechanism of the persistence context.
Member Entity
@Entity
@Getter
@Setter
public class Member {
protected Member() {}
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
public Member(String username) {
this.username = username;
}
}
Service method
@Transactional
public void addMember(String username) {
// create
Member member = new Member(username);
memberRepository.save(member);
// read
Member actual = memberRepository.findById(member.getId()).get();
log.info("Same Entity ? : {}", member == actual);
// update
String newUsername = "kitty";
member.setUsername(newUsername);
memberRepository.save(member);
// update verify
actual = memberRepository.findById(member.getId()).get();
log.info("Same Username ? : {}", member.getUsername().equals(actual.getUsername()));
// delete
memberRepository.delete(actual);
actual = memberRepository.findById(member.getId()).orElse(null);
log.info("Entity is null ? : {}", actual);
}
I think there is an entity on the PC(Persistence Context) before calling DELETE, and the DB also contains data.
When DELETE is called, FLUSH does not work immediately, so I understand that the DB still has data left, and it is removed from the PC(Persistence Context) after DELETE call.
And if you call findById again in that state, the PC(Persistence Context) does not have an entity, so you have to get it from DB.
Why is null returned from Actual?
Here is log
CodePudding user response:
And if you call findById again in that state, the PC(Persistence Context) does not have an entity, so you have to get it from DB.
That depends on the FlushModeType
. The default is AUTO
and this means that Hibernate uses the PersistenceContext to get the Entitiy after the delete.
If you want to read it from the database you have to use COMMIT
.
Example how to use it with a Query.
Member fromDB = em.createQuery("select m from Member m where m.id = :id", Member.class)
.setParameter("id", actual.getId())
.setFlushMode(FlushModeType.COMMIT)
.getSingleResult();
You can find everything about FlushModeType.COMMIT
in the Hibernate documentation: https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#flushing-commit