如何在同一个数据库表上映射两个JPA或Hibernate实体

时间:2015-03-12 10:47:50

标签: java database spring hibernate jpa

在我们的项目中,我们有一个实体'餐厅'有近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实施中,我们使用的是Criteria,其中包括&#39; RestaurantLite&#39;并返回餐馆名单,如下所示。

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

   // criteria related stuff

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

现在我们要删除所有hbm文件并使用注释。那么如何使用针对entites的注释来完成同样的事情呢?我们需要创建一个额外的课程&#39; RestaurantLite&#39;?如果那时,上述标准如何回归&#39;餐厅&#39;对象??

3 个答案:

答案 0 :(得分:44)

本主题以及如何将其用于延迟抓取属性,详细介绍了in this article

总结一下,以下映射将演示如何将多个实体映射到同一个数据库表:

@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实体传播更改。

  3. 此测试也可在GitHub上找到。

答案 1 :(得分:0)

我有一个类似的问题。我有两个类,基类 DocumentContent 和派生类 DocumentContentWithData

DocumentContent {
    private Long documentContentId;
    private InputStream contentStream;
    private File importFile;
    ... and several other attributes
}

DocumentContentWithData extends DocumentContent {}

我为这两个类定义了一个休眠映射,为 DocumentContent 类定义了一个没有 contentStream 的映射,为 DocumentContentWithData 类定义了一个映射与 contentStream

使用方法 Session.get(Class,ID)保存类 DocumentContentWithData 的数据,并且获取两个类的实例也可以。

但是下面的代码中的查询返回两个实体,一个作为 DocumentContent 的实例,另一个作为 DocumentContentWithData 的实例,尽管 importFile 在数据库中:

CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<DocumentContent> criteriaQuery = criteriaBuilder.createQuery(DocumentContent.class);
Root<DocumentContent> root = criteriaQuery.from(DocumentContent.class);
criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("importFile"), importFile));
Query<DocumentContent> query = session.createQuery(criteriaQuery);
List<DocumentContent> contentList = query.getResultList();

有人可以解释这种行为。当我不从 DocumentContent 派生类 DocumentContentWithData 并复制所有属性时,它将起作用。但是,这不是一个很好的解决方案。

答案 2 :(得分:-1)

您必须在类上添加注释@ Entity,@ Table(name =“RESTAURANT”),添加注释并在hbm文件中替换您的详细映射

这是一个完整的示例:http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/