Home > Software engineering >  I don't understand the mechanism of the JPA(Persistence Context)
I don't understand the mechanism of the JPA(Persistence Context)

Time:11-13

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

IDE Logs

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

  • Related