Hibernate - Dirty Check
Tags: hibernate, database, spring, java
Published: 2022-04-08 22:38:27

## 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.

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

and persist the created data to database via EntityManager.

```java
@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);
    }
}
```

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 (?, ?, ?)
```

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

```java
public void update() {
    CommentEntity commentEntity =
 entityManager.find(CommentEntity.class, 1l);
    entityManager.persist(commentEntity);
}
```

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=?
```

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

```java
public void update() {
    CommentEntity commentEntity = entityManager
                      .find(CommentEntity.class, 1l);
    commentEntity.setText("my other text");
    entityManager.persist(commentEntity);
}
```
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=?
```

> 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.

```java
@Transactional(readOnly = true)
```

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.