@Immutable in Hibernate – Hibernate中的@Immutable

最后修改: 2017年 3月 11日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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

在这篇文章中,我们将讨论如何在Hibernate中使实体、集合或属性Immutable>。

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

默认情况下,字段是可变的,这意味着我们能够对它们执行改变其状态的操作。

2. Maven

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:

为了使我们的项目启动和运行,我们首先需要在我们的pom.xml中添加必要的依赖项。由于我们使用的是Hibernate,我们将添加相应的依赖性

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.6.7.Final</version>
</dependency>

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

而且,由于我们正在使用HSQLDB,我们还需要。

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.3.4</version>
</dependency>

3. Annotation on Entities

3.实体的注释

First, let’s define a simple entity class:

首先,让我们定义一个简单的实体类。

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

    @Id
    @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:

正如你所注意到的,我们已经为我们的实体添加了@Immutable注解,所以如果我们试图保存一个Event

@Test
public void addEvent() {
    Event event = new Event();
    event.setId(2L);
    event.setTitle("Public Event");
    session.save(event);
    session.getTransaction().commit();
    session.close();
}

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.

还需要注意的是,在我们的EventGeneratedId实体中,我们添加了GeneratedValue注解,但这只有在我们创建实体时才会有影响。这是因为它指定了id的生成策略–由于Immutable注解的存在,任何其他操作都不会影响Id字段。

3.1. Updating the Entity

3.1.更新实体

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

现在,我们在保存一个实体时没有问题,让我们试着更新它。

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

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

Hibernate将简单地忽略update操作而不抛出一个异常。然而,如果我们删除@Immutable注解,我们会得到一个不同的结果。

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.

这告诉我们,我们的对象现在是可变的(mutable 是默认值,如果我们不包括注解的话),并且将允许更新完成它的工作。

3.2. Deleting an Entity

3.2.删除一个实体

When it comes to deleting an entity:

当涉及到删除一个实体时。

@Test
public void deleteEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);
    session.delete(event);
    session.getTransaction().commit();
}

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

4.对藏品的注释

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:

首先,让我们给我们的Event类添加一个集合。

@Immutable
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:

和以前一样,我们已经事先添加了注解,所以如果我们继续前进并尝试添加一个元素到我们的集合。

org.hibernate.HibernateException: 
  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

4.1.删除集合

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.

另一种情况是,当我们试图删除一个Collection,并且我们已经设置了@Cascade注解的时候,这个Collection是不可变的,会抛出一个异常。

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

因此,每当@Immutable出现,并且我们试图删除。

@Test
public void deleteCascade() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='Public Event'").list().get(0);
    String guest = event.getGuestList().iterator().next();
    event.getGuestList().remove(guest);
    session.saveOrUpdate(event);
    session.getTransaction().commit();
}

Output:

输出。

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

5. XML Notes

5.XML注释

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

最后,配置也可以通过mutable=false属性用XML完成。

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

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

然而,由于我们基本上是用注释的方法来实现这些例子的,所以我们将不涉及到使用XML的细节。

6. Conclusion

6.结论

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.

在这篇快速文章中,我们探讨了Hibernate中有用的@Immutable注解,以及它如何帮助我们在数据上定义更好的语义和约束。

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.

一如既往,所有这些例子和片段的实现都可以在GitHub项目中找到。这是一个基于Maven的项目,所以它应该很容易导入和运行。