Как сопоставить два объекта JPA или Hibernate в одной таблице базы данных

В нашем проекте у нас есть "Ресторан" с почти 30 полями (некоторые из них имеют отношения с другими сущностями). Поэтому каждый раз, когда нам нужен объект "Ресторан" даже для нескольких полей, все остальные извлекаются. Это влияет на производительность. Итак, в файле HBM мы написали два класса, указывающие на один и тот же физический класс и ту же таблицу базы данных, как показано ниже.

=== restaurant.hbm.xml ===
<!-- Light Weight Version -->
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="RestaurantLite" 
                dynamic-update="false" dynamic-insert="false">
<cache usage="read-only"/>
     <!-- few basic properties and relationships -->
</class>

<!-- Restaurant -->
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="Restaurant">
     <!-- all properties and relationships -->
</class>

В одной из реализаций DAO мы используем критерии, которые берут "RestaurantLite" и возвращают список ресторанов, как показано ниже.

Criteria criteria = session.createCriteria("RestaurantLite");

   // criteria related stuff

return new LinkedHashSet<Restaurant>(criteria.list());

Теперь мы хотим удалить все hbm файлы и использовать аннотации. Итак, как же можно сделать, используя аннотации для entites? Нужно ли создавать дополнительный класс "RestaurantLite"? Если тогда, как приведенные выше критерии возвращают объекты "Ресторан"

Ответы

Ответ 1

  Поскольку это очень распространенный вопрос, я решил написать подробную статью об этом.

Подводя итог, приведем следующие сопоставления, чтобы продемонстрировать, как можно сопоставить несколько сущностей в одной таблице базы данных:

@Entity(name = "Post")
public class Post {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    private String description;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

@Entity(name = "PostSummary")
@Table(name = "Post")
@Immutable
public class PostSummary {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Entity(name = "UpdatablePostSummary")
@Table(name = "Post")
@DynamicUpdate
public class UpdatablePostSummary {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

И Hibernate будет работать нормально:

@Test
public void testOneTableMultipleEntities() {
    doInTransaction(session -> {
        Post post = (Post) session.get(Post.class, 1L);
        PostSummary postSummary = (PostSummary) session.get(PostSummary.class, 1L);
        UpdatablePostSummary updatablePostSummary = (UpdatablePostSummary) session.get(UpdatablePostSummary.class, 1L);
        assertEquals(post.getName(), postSummary.getName());
        assertEquals(post.getName(), updatablePostSummary.getName());
        updatablePostSummary.setName("Hibernate Master Class Tutorial.");
    });
}
  1. PostSummary - это вид только для чтения вашей исходной сущности, поэтому я пометил его @Immutable.

  2. UpdatablePostSummary помечен @DynamicUpdate, поэтому вы также можете распространять изменения из этого объекта View.

Этот тест также доступен на GitHub.