Core Java

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

Java Hibernate Example Output for Changing Field Values Before Update and Insert

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.

Download
You can download the full source code of this example here: java hibernate change field value before update insert

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button