JPA Buddy
announcement - icon

JPA is huge! It covers nearly every aspect of communication between relational databases and the Java application and is deeply integrated into all major frameworks.

If you're using IntelliJ, JPA Buddy is super helpful. The plugin gently guides you through the subtleties of the most popular JPA implementations, visually reminds you of JPA features, generates code that follows best practices, and integrates intelligent inspections to improve your existing persistence code.

More concretely, it provides powerful tooling to generate Spring Data JPA repositories and methods, Flyway Versioned Migrations, Liquibase Differential Changelogs, DDL and SQL statements, DTO objects, and MapStruct interfaces.

Oh, and it actually generates JPA entities from an existing database and gradually update the data model as the database evolves! Yeah.

>> Become a lot more productive with JPA Buddy

Persistence top

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

Authors Top

If you have a few years of experience in the Java ecosystem, and you’d like to share that with the community, have a look at our Contribution Guidelines.

1. Overview

In this article, we'll talk about how we can make an entity, collection or attribute Immutable in Hibernate.

By default, fields are mutable, which means we're able to perform operations on them that change their state.

2. Maven

To get our project up and running, we first need to add the necessary dependencies into our pom.xml. And as we're working with Hibernate, we are going to add the corresponding dependency:


And, because we are working with HSQLDB, we also need:


3. Annotation on Entities

First, let's define a simple entity class:

@Table(name = "events_generated")
public class EventGeneratedId {

    @Column(name = "event_generated_id")
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private Long id;

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

    // standard setters and getters

As you have noticed we have added already the @Immutable annotation to our entity, so if we try and save an Event:

public void addEvent() {
    Event event = new Event();
    event.setTitle("Public Event");;

Then we should get the output:

Hibernate: insert into events (title, event_id) values (?, ?)

The output should be the same even if we remove the annotation, meaning there's no effect when we try to add an entity regardless of the annotation.

It's also important to note that in our EventGeneratedId entity, we added the GeneratedValue annotation, but this will only make a difference when we're creating an entity. That's because it specifies the generation strategy for the id – any other operations will not affect the Id field due to the Immutable annotation.

3.1. Updating the Entity

Now, we had no issue saving an entity, let's try to update it:

public void updateEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);
    event.setTitle("Public Event");

Hibernate will simply ignore the update operation without throwing an exception. However, if we remove the @Immutable annotation we get a different result:

Hibernate: select ... from events where title='My Event'
Hibernate: update events set title=? where event_id=?

What this tells us is that our object is now mutable (mutable is the default value if we don't include the annotation) and will allow the update to do its job.

3.2. Deleting an Entity

When it comes to deleting an entity:

public void deleteEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);

We'll be able to perform the delete regardless if it is mutable or not:

Hibernate: select ... from events where title='My Event'
Hibernate: delete from events where event_id=?

4. Annotation on Collections

So far we've seen what the annotation does to entities, but as we mentioned in the beginning, it can also be applied to collections.

First, let's add a collection to our Event class:

public Set<String> getGuestList() {
    return guestList;

Same as before, we've added the annotation beforehand, so if we go ahead and try to add an element to our collection:

  changed an immutable collection instance: [com.baeldung.entities.Event.guestList#1]

This time we get an exception because with collections we are not allowed to add nor delete them.

4.1. Deleting Collections

The other scenario where a Collection by being immutable will throw an exception it's whenever we try to delete and we have set the @Cascade annotation.

So, whenever @Immutable is present and we attempt to delete:

public void deleteCascade() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='Public Event'").list().get(0);
    String guest = event.getGuestList().iterator().next();


  changed an immutable collection instance:

5. XML Notes

Finally, the configuration can also be done using XML through the mutable=false attribute:

    <class name="com.baeldung.entities.Event" mutable="false">
        <id name="id" column="event_id">
            <generator class="increment"/>
        <property name="title"/>

However, since we basically implemented the examples using the annotation method, we will not get into details using XML.

6. Conclusion

In this quick article, we explore the useful @Immutable annotation out of Hibernate, and how that can help us define better semantics and constraints on our data.

As always, the implementation of all of these examples and snippets can be found in the GitHub project. This is a Maven-based project so it should be easy to import and run.

Persistence bottom
Get started with Spring Data JPA through the reference Learn Spring Data JPA course: >> CHECK OUT THE COURSE
Persistence footer banner
Comments are closed on this article!