Optimizing Hibernate and Spring Data JPA with @DynamicInsert and @DynamicUpdate

Paul Ravvich
Hibernate At the Gates of Mastery
3 min readApr 6, 2024

--

In this article, we will explore how the @DynamicInsert and @DynamicUpdate annotations can assist in optimizing SQL queries in Hibernate and Spring Data JPA, using a simple Person entity example.

Optimizing Hibernate and Spring Data JPA with @DynamicInsert and @DynamicUpdate

Hi, this is Paul, and welcome to this article, we explore how to use @DynamicInsert and @DynamicUpdate annotations for Hibernate query optimization.

Basics of @DynamicInsert and @DynamicUpdate

These annotations enable the generation of SQL queries that include only the modified fields, reducing the amount of data transmitted and decreasing the load on the database.

It’s important to note that for these annotations to be effective, the entity must be in a certain state. Specifically, the entity must be in a managed state for Hibernate to track changes. This means the entity should be either retrieved from the database within the current session or attached to the session if it was detached. If an entity is in a detached state, where it is not associated with any Hibernate session, changes made to it won’t trigger the dynamic SQL generation upon update or insert.

Read more about Entity Statuses and Entity Lifecycle in Hibernate

Read more about the Dirty Checking mechanism in Hibernate

Example of @DynamicInsert and @DynamicUpdate

import jakarta.persistence.*;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Getter
@Setter
@ToString
@DynamicInsert
@DynamicUpdate
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "persons")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name")
private String name;

@Column(name = "age")
private Integer age;

// equals and hashCode
}

SQL table:

CREATE TABLE persons (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255),
age INTEGER
);

Examples of Generated Queries

Insert without @DynamicInsert annotation:

INSERT INTO Person (name, age) VALUES ('John', NULL);

Insert with @DynamicInsert annotations:

INSERT INTO Person (name) VALUES ('John');

Update without @DynamicUpdate annotation:

UPDATE Person SET name = 'Mike', age = <old_value> WHERE id = ?;

Here, <old_value> implies that the value of age remains unchanged but is still included in the query. In a real SQL query, <old_value> would be replaced with the actual value of the age field.

Update with @DynamicUpdate annotation:

UPDATE Person SET name = 'Mike' WHERE id = ?;

In this case, thanks to @DynamicUpdate, the update query includes only the fields that were changed. If only the name was changed, then the query will include only the name field.

Integration with Spring Data JPA

The @DynamicInsert and @DynamicUpdate annotations are fully compatible with Spring Data JPA. Here is a simple repository example:

public interface PersonRepository extends JpaRepository<Person, Long> {}

@Autowired
private PersonRepository personRepository;

public void addOrUpdatePerson(Person person) {
personRepository.save(person);
}

Spring Data automatically manages the session and transactions, allowing Hibernate to track changes in entities and optimize queries based on @DynamicInsert and @DynamicUpdate.

Conclusion

@DynamicInsert and @DynamicUpdate significantly improve the performance of database operations in applications using Hibernate and Spring Data JPA. They make the code cleaner and simplify data model management, contributing to the development of high-performance and easily maintainable applications.

Thank you for reading until the end. Before you go:

Paul Ravvich

--

--

Paul Ravvich
Hibernate At the Gates of Mastery

Software Engineer with over 10 years of XP. Join me for tips on Programming, System Design, and productivity in tech! New articles every Tuesday and Thursday!