当前位置: 首页 > 知识库问答 >
问题:

Hibernate-一个表多个实体

杨和蔼
2023-03-14

首先,我已经阅读了Hibernate——一个包含多个实体的表?。

然而,我希望将两个实体映射到同一个表,但我希望它们都是实体,我可以从中选择。我的意思是:

  • 一个表:人(id、姓名、出生日期、城市、街道、邮政编码)。
  • 两个实体:人(id、name、dateOfBirth)、地址(id、城市、街道、邮政编码)。

实体之间是1:1的关系,但数据库中仍然是1个表。

如果我在上面的链接中使用建议的解决方案(组件关键字),我不能直接查询地址(我可以通过个人实体访问地址)。我希望能够做到这一点

session.createCriteria(Adres.class)

我该怎么做?

更新:我在地址映射中尝试了实体之间的一对一关联:

<one-to-one name="Person " class="model_mapowanie_xml.Person "/>

亲自绘制地图:

<one-to-one name="Address" class="model_mapowanie_xml.Address "/>

两个类都有引用另一个的字段。选择记录可以很好地做到这一点。但是,如何在一个事务中添加使用两个实体的记录?(Id是db生成的)

Address ad = new Address();
ad.setProperty("Sydney");
Person p = new Person();
p.setProperty("John");
p.setAddress(ad);
session.save(p);

并且只有Person部分被保存,address属性仍然为空。

共有2个答案

牛骞仕
2023-03-14

您应该能够使用@Table注释来完成它。这些实体将被视为不同的实体,但将映射到同一个表上。

@Entity
@Table(name="PERSON_TABLE")
class Person {}


@Entity
@Table(name"PERSON_TABLE")
class Address {}

编辑:

如果要在一个事务中保存两个实体,则必须使用Session显式保存它们,或者将cascade属性设置为对关系进行级联操作。我猜当你对某人做某事时,你想对地址进行级联操作。如果使用注释,请参见CascadeType。

在你的hbm中,它看起来像

裴建华
2023-03-14

使用JPA和Hibernate实现这一点非常简单。

假设您正在使用以下book数据库表:

现在,您可以将两个实体:BookBook汇总映射到此表。

首先,我们将创建一个BaseBook抽象类,该类将由所有实体扩展:

@MappedSuperclass
public abstract class BaseBook<T extends BaseBook> {
 
    @Id
    @GeneratedValue
    private Long id;
 
    @NaturalId
    @Column(length = 15)
    private String isbn;
 
    @Column(length = 50)
    private String title;
 
    @Column(length = 50)
    private String author;
 
    public Long getId() {
        return id;
    }
 
    public T setId(Long id) {
        this.id = id;
        return (T) this;
    }
 
    public String getIsbn() {
        return isbn;
    }
 
    public T setIsbn(String isbn) {
        this.isbn = isbn;
        return (T) this;
    }
 
    public String getTitle() {
        return title;
    }
 
    public T setTitle(String title) {
        this.title = title;
        return (T) this;
    }
 
    public String getAuthor() {
        return author;
    }
 
    public T setAuthor(String author) {
        this.author = author;
        return (T) this;
    }
}

现在,Booksum实体只是扩展了BaseBook超类并没有添加额外的实体属性。

@Entity(name = "BookSummary")
@Table(name = "book")
public class BookSummary extends BaseBook<BookSummary> {
 
}

另一方面,Book实体扩展了BaseBook超类,并映射了properties属性。

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(
    name = "jsonb",
    typeClass = JsonBinaryType.class
)
@DynamicUpdate
public class Book extends BaseBook<Book> {
 
    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private String properties;
 
    public String getProperties() {
        return properties;
    }
 
    public Book setProperties(String properties) {
        this.properties = properties;
        return this;
    }
 
    public ObjectNode getJsonProperties() {
        return (ObjectNode) JacksonUtil
            .toJsonNode(properties);
    }
}

通过这种方式,您可以持久化书籍实体:

entityManager.persist(
    new Book()
        .setIsbn("978-9730228236")
        .setTitle("High-Performance Java Persistence")
        .setAuthor("Vlad Mihalcea")
        .setProperties(
            "{" +
                "   \"publisher\": \"Amazon\"," +
                "   \"price\": 44.99," +
                "   \"publication_date\": \"2016-20-12\"," +
                "   \"dimensions\": \"8.5 x 1.1 x 11 inches\"," +
                "   \"weight\": \"2.5 pounds\"," +
                "   \"average_review\": \"4.7 out of 5 stars\"," +
                "   \"url\": \"https://amzn.com/973022823X\"" +
            "}"
        )
);

书籍摘要

entityManager.persist(
    new BookSummary()
        .setIsbn("978-1934356555")
        .setTitle("SQL Antipatterns")
        .setAuthor("Bill Karwin")
);

您可以获取BookSummary实体:

BookSummary bookSummary = entityManager
    .unwrap(Session.class)
    .bySimpleNaturalId(BookSummary.class)
    .load("978-9730228236");
 
assertEquals(
    "High-Performance Java Persistence",
    bookSummary.getTitle()
);

书籍实体,如果需要:

Book book = entityManager
    .unwrap(Session.class)
    .bySimpleNaturalId(Book.class)
    .load("978-9730228236");
 
assertEquals(
    "High-Performance Java Persistence, 2nd edition",
    book.getTitle()
);

因此,将多个实体映射到同一个数据库表,不仅可以让我们更有效地获取数据,而且还可以加快脏检查过程,因为Hibernate必须检查更少的实体属性。

使用这种方法的唯一缺点是,必须确保不会为同一数据库表记录获取多个实体类型,否则,刷新持久性上下文时可能会导致不一致。

 类似资料:
  • 我正在尝试编写一个简单的应用程序,其中包含一个跟踪每个用户支付的款项的表和一个包含每个用户支付的总金额(所有付款的总和)的第二个表。目前,两个表都有相同的字段(firstName、lastName、金额),我已经将它们从同一个Java类映射到多个表,我无法将该类映射到多个表。对此有什么简单的解决方案吗?

  • 我在实体类中设置一些hibernate注释时遇到问题。 我的问题是:我如何告诉Hibernate,它应该在一个表中存储地址、名称和客户信息。此表应包含以下列:ID、给定、姓氏、街道、门牌号、邮政编码、城市、电话、评论。目前,Hibernate在mysql数据库中为每个实体生成一个表。因此,有必要在每个实体类(客户、名称、地址)中定义@Id。但我想用一个@Id为客户保留一张表中的所有信息。 我怎样才

  • 当我映射同一个实体时,就像这里回答的那样: Hibernate与同一实体的多对多关联 在“tbl_friends”表中,我有相同含义的行。例如,我有id=1的用户和id=2的用户。在“tbl_friends”表中,当他们作为朋友链接时,我有两行 使用Hibernate或JPA引用是否可以在一行(1-2或2-1)中建立这种关系?

  • 问题内容: 我有一个实体- 。由描述。 Hibernate为每个实体创建一个表,因此当我调用时,我的数据总是保存到该表中。 现在,我需要另一个表来存储相同类型的数据,并且只需要将我的实体保存到该表中。 数据结构 (类似这样): 使用这个 : 和结果,我应该在和 中。 由于系统限制,我无法将这两个对象放在一个表中。(即使创建额外的字段也是个坏主意)。 我可以不进行子类化吗?使用Programmati

  • Hibernate为每个实体创建一个表,因此当我调用时,我的数据总是保存到这个表中。 现在,我需要另一个表来存储相同类型的数据,并且我只需要将我的实体保存到该表中。 数据结构(类似于以下内容): 由于系统的限制,我不能将这两个对象放在一个表中。(即使创建额外字段也是坏主意)。 我可以在不进行子类化的情况下这样做吗?使用programmaticaly hibernate配置?

  • 我的数据模型中有以下实体关系。 ERD Hibernate实体: 要求:我想用实体B的连接获取查询实体C,同时也急切地获取实体D。查询完成后,我希望如果我执行,它不应导致hibernate中的N 1查询问题。 我正在尝试以下JPQL查询: 这导致结果重复,因为与实体D交叉连接。我得到的不是一个结果,而是n个结果,其中n是实体D列表的大小。 我该如何避免这种情况?有没有办法在JPQL中不交叉连接地获