简体   繁体   English

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

[英]How to map two JPA or Hibernate entities on the same database table

In our project, we have an entity 'Restaurant' with nearly 30 fields(some have relationships with other entities).在我们的项目中,我们有一个包含近 30 个字段的实体“餐厅”(有些与其他实体有关系)。 So, every time we need a 'Restaurant' object even for a few fields, all the others are retrieved.因此,每次我们需要一个 'Restaurant' 对象时,即使是几个字段,所有其他字段都会被检索。 This effects the performance.这会影响性能。 So, in the HBM file, we wrote two classes both pointing to the same physical class and same database table, as shown below.因此,在 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>

In one of the DAO implementations, we are using Criteria which takes 'RestaurantLite' and returning list of restaurants as shown below.在 DAO 实现之一中,我们使用 Criteria,它采用“RestaurantLite”并返回餐厅列表,如下所示。

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

   // criteria related stuff

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

Now we want to remove all hbm files and use annotations.现在我们要删除所有 hbm 文件并使用注释。 So how the same can be done using annotations for entites?那么如何使用实体的注释来完成同样的事情呢? Do we need to create an extra class 'RestaurantLite'?我们是否需要创建一个额外的类“RestaurantLite”? If then, how the above criteria returns 'Restaurant' objects??如果是这样,上述标准如何返回“餐厅”对象?

To summarize it, the following mappings are going to demonstrate how you can map multiple entities to the same database table:总而言之,以下映射将演示如何将多个实体映射到同一个数据库表:

@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;
    }
}

And Hibernate will work just fine:并且 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. The PostSummary is just a read-only View over your original entity, hence I annotated it with @Immutable . PostSummary只是原始实体的只读视图,因此我用@Immutable对其进行了@Immutable

  2. The UpdatablePostSummary is marked with @DynamicUpdate and so you can propagate changes from this View entity too. UpdatablePostSummary@DynamicUpdate标记,因此您也可以从该视图实体传播更改。

This test is also available on GitHub .此测试也可在GitHub 上获得

I have a similar Problem.我有一个类似的问题。 I have two classes, the base class DocumentContent and a derived class DocumentContentWithData :我有两个类,基类DocumentContent和派生类DocumentContentWithData

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

DocumentContentWithData extends DocumentContent {}

I defined a hibernate mapping for the two classes, for the class DocumentContent a mapping without the contentStream and for the class DocumentContentWithData a mapping with the contentStream .我为这两个类定义了一个休眠映射,对于类DocumentContent是一个没有contentStream的映射,对于类DocumentContentWithData是一个带有contentStream的映射。

Saving the data with the class DocumentContentWithData works and also getting the instances for both classes works with the method Session.get(Class, ID) .使用类DocumentContentWithData保存数据,并且使用Session.get(Class, ID)方法获取两个类的实例。

However the query in the following code returns two entities, one as instance of DocumentContent and the other as instance of DocumentContentWithData although there is only one entry with the importFile in the database:然而,在下面的代码返回两个实体,一个作为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();

Can someone explain this behavior.有人可以解释这种行为。 When I do not derive the class DocumentContentWithData from DocumentContent and duplicate all attributes it works.当我没有得到来自DocumentContentDocumentContentWithData和复制所有属性,它的工作原理。 However this is not a very nice solution.然而,这不是一个很好的解决方案。

You have to add annotation @Entity,@Table(name="RESTAURANT") on your class, add annotations and replace your detailed mapping in hbm file by您必须在类上添加注释@Entity,@Table(name="RESTAURANT"),添加注释并替换 hbm 文件中的详细映射
. .

Here a complete example: http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/这里有一个完整的例子: http : //viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM