Change Field Value Before Update and Insert in Hibernate
Changing field values before inserting or updating data in a database is a common requirement in many applications. In Hibernate, there are several ways to achieve this, such as customizing the setter method, using lifecycle callbacks, leveraging the @ColumnTransformer
annotation, and employing custom SQL INSERT
and UPDATE
statements. This article will explore various techniques with code examples.
1. Customize the Setter Method
One simple way to modify field values before saving or updating an entity in Hibernate is by customizing the setter method of the entity class. We can perform any transformation or validation inside the setter before storing the value.
Let’s say we have an Employee
entity with a name
field that we want to automatically convert to uppercase before inserting or updating.
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public Employee() {} public Employee(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } // Custom setter method to change the name to uppercase public void setName(String name) { if (name != null) { this.name = name.toUpperCase(); } else { this.name = null; } } }
The setter method for the name
field changes the value to uppercase before saving it in the entity, making sure this change happens every time the field is set, whether it’s for inserting or updating data.
With our entity set up, let’s look at a simple application to test our implementation.
public class Changevaluehibernate { public static void main(String[] args) { // Create the EntityManagerFactory using the persistence unit defined in persistence.xml EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("EmployeePU"); // Create the EntityManager EntityManager entityManager = entityManagerFactory.createEntityManager(); try { // Insert a new employee with lowercase name entityManager.getTransaction().begin(); Employee employee = new Employee(); employee.setName("mr fish"); entityManager.persist(employee); entityManager.getTransaction().commit(); System.out.println("Inserted Employee: " + employee.getName()); // Update the employee's name entityManager.getTransaction().begin(); employee.setName("mr fish"); entityManager.merge(employee); entityManager.getTransaction().commit(); System.out.println("Updated Employee: " + employee.getName()); } finally { entityManager.close(); entityManagerFactory.close(); } } }
Output: The name
is automatically converted to uppercase when set, both during the insert (MR FISH
) and the update (MR FISH
).
2. Using @PrePersist
and @PreUpdate
Annotations
Another simple way to modify a field value before persisting an entity is by using the @PrePersist
and @PreUpdate
lifecycle callback annotations. We can update the Employee
entity to include these annotations:
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public Employee() { } public Employee(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // Lifecycle callback to convert name to uppercase before persisting @PrePersist @PreUpdate private void transformName() { if (name != null) { name = name.toUpperCase(); } } }
The @PrePersist
method runs before the entity is saved to the database for the first time, and @PreUpdate
runs before it’s updated. The transformName()
method ensures that the name is always converted to uppercase before either of these database operations occurs.
Output: The output is similar to the setter method approach since the transformation happens before the insert and update.
Hibernate: insert into Employee (name) values (?) Inserted Employee: TOM FISH Updated Employee: TOM FISH
3. Using Entity Listeners
Another way to achieve this is by using entity listeners. This allows us to separate the logic from the entity itself.
Creating an EmployeeListener
We can create a separate listener class to handle the transformations:
public class EmployeeListener { @PrePersist @PreUpdate public void transformName(Employee employee) { if (employee.getName() != null) { employee.setName(employee.getName().toUpperCase()); } } }
Next, we modify the Employee
entity to use this listener:
@Entity @Table(name = "employee") @EntityListeners(EmployeeListener.class) public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public Employee() { } public Employee(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
The @EntityListeners
annotation is used to specify a listener class that contains callback methods for the entity lifecycle. In our case, we have created an EmployeeListener
class, which includes the transformName
method marked with @PrePersist
and @PreUpdate
. This method is automatically invoked by Hibernate before the entity is inserted or updated in the database.
4. Using @ColumnTransformer
Hibernate provides the @ColumnTransformer
annotation, which allows us to define how a field is transformed when reading from or writing to the database. Here, we transform the name
field so that it is stored in uppercase in the database, using @ColumnTransformer
.
@Entity @Table(name = "employee") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column @ColumnTransformer(write = "UPPER(?)") private String name; public Employee() { } public Employee(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
The @ColumnTransformer(write = "UPPER(?)")
annotation indicates that the name
field should be converted to uppercase before it is saved to the database. This approach is useful if we prefer to keep the transformation logic at the database level.
Output:
Hibernate: insert into employee (name) values (UPPER(?)) Inserted Employee: tommy fish Updated Employee: tommy fish
Although the value of name
at the Java level remains in its original form (tommy fish
), the transformation happens at the database level. The @ColumnTransformer
ensures that the value stored in the database is uppercase even if the in-memory value is not.
5. Using Custom SQL INSERT
and UPDATE
Statements
For more complex transformations or scenarios where we need full control over the SQL operations, Hibernate allows us to define custom SQL for INSERT
and UPDATE
operations using the @SQLInsert
and @SQLUpdate
annotations. Below we define custom SQL statements to ensure that the name
is always stored in uppercase when inserted or updated.
@Entity @SQLInsert(sql = "INSERT INTO employee (name) VALUES (UPPER(?))") @SQLUpdate(sql = "UPDATE employee SET name = UPPER(?) WHERE id = ?") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public Employee() { } public Employee(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
The @SQLInsert
annotation allows you to define a custom SQL INSERT statement that converts the name
to uppercase, while the @SQLUpdate
annotation specifies a custom SQL UPDATE statement that performs the same transformation. This method is helpful when we need exact control over SQL operations or when the transformation is too complicated for annotations like @ColumnTransformer
to manage.
The output will be similar to the @ColumnTransformer
approach since the conversion to uppercase occurs at the SQL level. The SQL statements enforce this behaviour directly before data is written to the database.
6. Conclusion
In this article, we explored various methods to change field values before inserting or updating them in Hibernate, focusing on the name
field of an Employee
entity. We discussed how to customize setter methods, use lifecycle callbacks, implement @ColumnTransformer
, and define custom SQL statements with @SQLInsert
and @SQLUpdate
. We also covered how Entity Listeners can be used to handle transformations at a broader level.
7. Download the Source Code
This article discusses how to change a field value in Java Hibernate before performing an update or insert operation.
You can download the full source code of this example here: java hibernate change field value before update insert