DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Hibernate - Dirty Check
Yiğit Erkal
Yiğit Erkal

Posted on • Updated on

Hibernate - Dirty Check

What is 'Dirty Check'? πŸ€”

Hibernate checks the entity objects that are in the 'managed' status, that is, they have been added to the persistence context. When an entity object is loaded, a copy of all properties of that entity object is created. At the time of synchronization, which we call flush time, the properties of the entity object are matched with the properties of the loaded object and the difference is checked. This process is called β€œHibernate Dirty Check”.

Let's start with a basic entity.

@Entity
@Table(name="comment")
@DynamicUpdate
public class CommentEntity{
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Long id;
    private String text;
    private String owner;
}
Enter fullscreen mode Exit fullscreen mode

and persist the created data to database via EntityManager.

@Repository
@Transactional
public class CommentRepository {
    @Autowired
    EntityManager entityManager;

    public void save() {
        CommentEntity commentEntity= new CommentEntity();
        commentEntity.setText("my comment");
        commentEntity.setOwner("my owner");
        entityManager.persist(commentEntity);
    }
}
Enter fullscreen mode Exit fullscreen mode

When we call the save method of the bean named CommentRepository, it will insert into the database. The SQL output is as follows.

Hibernate: call next value for hibernate_sequence
Hibernate: insert into comment (id, text, owner) values (?, ?, ?)
Enter fullscreen mode Exit fullscreen mode

What if we try to persist the same data to our database after we get it?

public void update() {
    CommentEntity commentEntity =
 entityManager.find(CommentEntity.class, 1l);
    entityManager.persist(commentEntity);
}
Enter fullscreen mode Exit fullscreen mode

Here is the output that only makes a select query by hibernate

Hibernate: select commententity0_.id as id1_1_0_, commententity0_.text 
as text2_1_0_, commententity0_.owner 
as owner3_1_0_ from comment commententity0_ 
where commententity0_.id=?
Enter fullscreen mode Exit fullscreen mode

Well... What if we change the property of the object and persist again?

public void update() {
    CommentEntity commentEntity = entityManager
                      .find(CommentEntity.class, 1l);
    commentEntity.setText("my other text");
    entityManager.persist(commentEntity);
}
Enter fullscreen mode Exit fullscreen mode

Now, Hibernate will apply update action after select

Hibernate: select commententity0_.id as id1_1_0_, 
commententity0_.text as text2_1_0_, commententity0_.owner 
as owner3_1_0_ from comment commententity0_ where commententity0_.id=?
Hibernate: update comment set text=? where id=?
Enter fullscreen mode Exit fullscreen mode

Each time, Hibernate checks the properties of the entity object with the last loaded snapshot. If there is a change, it performs the update.
That's why this situation is called "Hibernate Dirty Check". In fact, it causes a performance loss.

What is the solution? 🧠

When an entity is loaded, the 'Hibernate dirty checking mechanism' compares the snapshot of the current entity with the loaded entity, but we can also turn off this comparison when we are not going to update it.

@Transactional(readOnly = true)
Enter fullscreen mode Exit fullscreen mode

If we mark the method we are processing as readOnly = true, there will be no 'Hibernate dirty check' operation, as there will be no update operation. This gives us performance.

Top comments (0)

🌚 Life is too short to browse without dark mode