We can update an entity only if some field value has changed by using the @DynamicUpdate
annotation provided by Hibernate. This annotation tells Hibernate to generate SQL updates only for the changed fields, reducing unnecessary database operations. In this post, we are going to explore the Hibernate @DynamicUpdate Example.
The primary purpose of the @DynamicUpdate
annotation is to optimize the update operation for an entity. When this annotation is applied to an entity class, Hibernate generates an SQL update statement that only includes the columns whose values have been modified in the entity, rather than updating all columns. This can lead to more efficient database updates, reducing unnecessary work in the database. Let’s see how to use JPA @DynamicUpdate annotation.
Note – Hibernate @DynamicUpdate annotation is used with class, not with method.
@Entity
@DynamicUpdate
public class Student implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "roll_number")
private String rollNumber;
@Column(name = "university")
private String university;
//getter & setter
}
Consider we want to update only one filed name. Let’s see how the hibernate query gets generated when we use Hibernate @DynamicUpdate annotation and when we don’t use Hibernate annotation. We want to update the student entity using the Spring Data JPA save() method. Consider we have a StudentRepository interface.
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}
StudentServiceImpl.java
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentRepository studentRepository;
@Transactional
public Student update(Student student) {
Student updateResponse = studentRepository.save(student);
return updateResponse;
}
}
Query generated without using Hibernate @DynamicUpdate and with using @DynamicUpdate while updating name field only
Let’s see what query hibernate generates when we update only name fields in both cases i.e without using @DynamicUpdate annotation and with using @DynamicUpdate annotation.
Without using Hibernate @DynamicUpdate
Hibernate:
update
student
set
name=?,
roll_number=?,
university=?
where
id=?
Using Hibernate @DynamicUpdate
Hibernate:
update
student
set
name=?
where
id=?
As we can see hibernate is only generating an update query for the name field if we use @DynamicUpdate annotation. This is the big advantage of using Hibernate @DynamicUpdate annotation.
Hibernate @DynamicUpdate Example using Spring Boot
Let’s see a complete example from scratch.
Create a maven project and update pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>springdatajpa</groupId>
<artifactId>springdatajpa</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
Define entity – Student.java
package com.springboot.entity;
import org.hibernate.annotations.DynamicUpdate;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@DynamicUpdate
public class Student implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "roll_number")
private String rollNumber;
@Column(name = "university")
private String university;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNumber() {
return rollNumber;
}
public void setRollNumber(String rollNumber) {
this.rollNumber = rollNumber;
}
public String getUniversity() {
return university;
}
public void setUniversity(String university) {
this.university = university;
}
}
Define StudentService.java
package com.springboot.service;
import com.springboot.entity.Student;
public interface StudentService {
public Student save(Student student);
public Student update(Student student);
/*
public Student get(Long id);
public List<Student> getStudents(String name);
//public List<Student> getStudents();
public void delete(Student student);
*/
}
Define Repository interface
package com.springboot.repository;
import com.springboot.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}
Define StudentServiceImpl.java
package com.springboot.serviceimpl;
import com.springboot.entity.Student;
import com.springboot.repository.StudentRepository;
import com.springboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentRepository studentRepository;
@Transactional
public Student save(Student student) {
Student createResponse = null;
createResponse = studentRepository.save(student);
return createResponse;
}
@Transactional
public Student update(Student student) {
Student updateResponse = studentRepository.save(student);
return updateResponse;
}
/*
@Transactional
public Student get(Long id) {
Optional<Student> response = studentRepository.findById(id);
Student getResponse = response.get();
return getResponse;
}
@Transactional
public List<Student> getStudents(String name) {
List<String> names = new ArrayList<>();
names.add(name);
List<Student> response = new ArrayList<>();
//response = studentRepository.findDistinctByNameNotIn(names);
return response;
}
@Transactional
public void delete(Student student) {
//studentRepository.delete(student);
}
*/
}
Define controller class
package com.springboot.controller;
import com.springboot.config.MainConfigFiles;
import com.springboot.entity.Student;
import com.springboot.repository.StudentRepository;
import com.springboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private MainConfigFiles mainConfigFiles;
@Autowired
private StudentService studentService;
@Autowired
private StudentRepository studentRepository;
@PostMapping("/create")
public Student createStudent1(@RequestBody Student student) {
//System.out.println(mainConfigFiles.getMessage2());
Student createResponse = studentService.save(student);
return createResponse;
}
@PutMapping("/update")
public Student updateStudent(@RequestBody Student student) {
Student updateResponse = studentService.update(student);
return updateResponse;
}
/* @GetMapping("/{id}")
public Student getStudent(@PathVariable Long id) {
Student getReponse = studentService.get(id);
return getReponse;
}*/
/* @GetMapping("/{name}")
public List<Student> getStudent(@PathVariable String name) {
List<Student> getReponse = studentService.getStudents(name);
return getReponse;
}*/
/* @GetMapping("/{students}")
public List<Student> getStudent() {
List<Student> getReponse = studentService.getStudents();
return getReponse;
}*/
/* @DeleteMapping("/delete")
public String deleteStudent(@RequestBody Student student) {
studentService.delete(student);
return "Record deleted succesfully";
}
@GetMapping("/getcustomfieldsbasisofuserinput")
public String deleteStudent(@RequestParam String fields) {
System.out.println(fields);
//studentService.delete(student);
return "Record deleted succesfully";
}
@GetMapping("/{name}")
public List<Student> finddistinctbyname(@PathVariable String name) {
List<Student> students = studentService.getStudents(name);
return students;
}*/
}
Define config class
package com.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@EnableJpaRepositories(basePackages = "com.springboot.repository")
public class MainConfigFiles {
/* @Value("${welcome.message}")
private String message2;
private MainConfigFiles mainConfigFiles;
@Bean
public MainConfigFiles jpaConfig(){
mainConfigFiles = new MainConfigFiles();
mainConfigFiles.setMessage2(message2);
return mainConfigFiles;
}
public String getMessage2() {
return message2;
}
public void setMessage2(String message2) {
this.message2 = message2;
}*/
}
Define main class
package com.springboot.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = "com.springboot.*")
@EntityScan("com.springboot.*")
public class SpringMain {
public static void main(String[] args) {
SpringApplication.run(SpringMain.class, args);
}
}
Testing using postman
Request Data for create
{
"name": "rakesh",
"rollNumber": "0126CS071",
"university": "rgtu"
}

Request Data for update
{
"id": 1,
"name": "rakesh",
"rollNumber": "0126CS071",
"university": "rgtu"
}

Let’s see a few points about Hibernate @DynamicUpdate Example.
The @DynamicUpdate
annotation is typically used in Java Persistence API (JPA) frameworks like Hibernate to control the update behavior of entities. Here are five key points about the @DynamicUpdate
annotation:
- Selective Update Optimization:
The primary purpose of the@DynamicUpdate
annotation is to optimize the update operation for an entity. When this annotation is applied to an entity class, Hibernate generates an SQL update statement that only includes the columns whose values have been modified in the entity, rather than updating all columns. - Reduced Database Load:
By updating only the changed columns, the@DynamicUpdate
annotation can reduce the load on the database server during update operations. This can be particularly beneficial in scenarios where frequent updates occur, as it minimizes the amount of data transferred between the application and the database. - Example Usage:
To use the@DynamicUpdate
annotation, we typically annotate your entity class with@Entity
and then add@DynamicUpdate
above the class declaration. Here’s an example:
import org.hibernate.annotations.DynamicUpdate;
@Entity
@DynamicUpdate
public class Product {
// Entity fields and methods
}
- Considerations:
While@DynamicUpdate
can be beneficial for optimizing update operations, it may not be suitable for all scenarios. It is important to evaluate whether the benefits of reduced database load and improved update efficiency outweigh any potential drawbacks. Additionally, be aware that this annotation may not work as expected in all JPA implementations and may have limitations in some cases.
In summary, the @DynamicUpdate
annotation in JPA is a useful tool for optimizing update operations in Hibernate and similar JPA implementations. It allows you to reduce database load and improve performance by updating only the changed columns in an entity, offering fine-grained control over the update behavior. However, it should be used judiciously and tested thoroughly to ensure it meets the requirements of your specific application.
Question 1: What is the primary purpose of the Hibernate @DynamicUpdate
annotation?
A. To enable automatic table creation
B. To optimize update operations
C. To define primary keys
D. To create a new entity class
Question 2: How does the @DynamicUpdate
annotation affect the update behavior of Hibernate entities?
A. It inserts new records in the database.
B. It updates all columns in the entity.
C. It generates SQL update statements for modified columns only.
D. It enforces unique constraints on entity fields.
Question 3: Can you apply the @DynamicUpdate
annotation to specific entity classes, or does it affect all entities in a Hibernate application?
A. It affects all entities in the application.
B. It can only be applied to abstract classes.
C. You can apply it selectively to specific entity classes.
D. It applies only to entity fields, not entire classes.
Question 4: What are some potential benefits of using the @DynamicUpdate
annotation in Hibernate?
A. Increased database load during update operations.
B. Improved database update performance.
C. Automatic generation of primary keys.
D. Fine-grained control over table creation.
Question 5: Are there any considerations or limitations when using the @DynamicUpdate
annotation in Hibernate?
A. It works seamlessly with all JPA implementations.
B. Careful evaluation is needed to determine if the benefits outweigh potential drawbacks.
C. It must be used with the @Entity
annotation.
D. It can only be applied to non-relational databases.
Now, here are the correct answers:
Answer 1: B. To optimize update operations
Answer 2: C. It generates SQL update statements for modified columns only.
Answer 3: C. You can apply it selectively to specific entity classes.
Answer 4: B. Improved database update performance.
Answer 5: B. Careful evaluation is needed to determine if the benefits outweigh potential drawbacks.
Hibernate @DynamicUpdate docs.
That’s all about Hibernate @DynamicUpdate Example
Other JPA Examples.
- Spring Data JPA CrudRepository findById()
- Spring Data JPA JpaRepository getOne()
- Spring Data CrudRepository saveAll() and findAll().
- Spring Data CrudRepository existsById()
- Spring Data JPA delete() vs deleteInBatch()
- Spring Data JPA deleteAll() Vs deleteAllInBatch()
- Spring Data JPA JpaRepository deleteAllInBatch()
- Spring Data JPA deleteInBatch() Example
- Spring Data JPA JpaRepository saveAndFlush() Example
- Spring Data JPA CrudRepository count() Example