Optimizing Hibernate and Spring Data JPA with @DynamicInsert
and @DynamicUpdate
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.
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:
- Please consider clapping and following the writer! 👏
- Follow us on Twitter(X), LinkedIn