web-dev-qa-db-ja.com

2つのJPAまたはHibernateエンティティを同じデータベーステーブルにマッピングする方法

このプロジェクトでは、30近くのフィールドを持つエンティティ「レストラン」があります(一部は他のエンティティと関係があります)。そのため、いくつかのフィールドであっても「Restaurant」オブジェクトが必要になるたびに、他のすべてのフィールドが取得されます。これはパフォーマンスに影響します。そのため、HBMファイルでは、以下に示すように、同じ物理クラスと同じデータベーステーブルを指す2つのクラスを作成しました。

=== 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実装の1つでは、以下に示すように、「RestaurantLite」を取り、レストランのリストを返すCriteriaを使用しています。

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

   // criteria related stuff

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

次に、すべてのhbmファイルを削除し、注釈を使用します。では、どのようにエンティティの注釈を使用して同じことを行うことができますか?追加のクラス「RestaurantLite」を作成する必要がありますか?もしそうなら、上記の基準はどのように「レストラン」オブジェクトを返しますか?

25
Raj44

これは非常に一般的な質問なので、私は 詳細な記事 について書くことにしました。

要約すると、次のマッピングは、複数のエンティティを同じデータベーステーブルにマップする方法を示しています。

@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 でも利用できます。

46
Vlad Mihalcea