7

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

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

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

所以这是实体之间的 1:1 关系,但在 DB 中仍然是 1 个表。

如果我使用上述链接中建议的解决方案(组件关键字)来执行此操作,我无法直接查询地址(我可以通过 Person 实体访问它)。我希望能够做到

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 部分,地址属性保持为空。

4

2 回答 2

5

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

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


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

编辑:

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

在您的 hbm 中,它看起来像 <one-to-one name="Person" class="model_mapowanie_xml.Person" cascade="all"/>

于 2013-08-31T12:29:33.203 回答
5

这很容易通过 JPA 和 Hibernate 实现。

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

在此处输入图像描述

映射实体

现在,您可以将两个实体:Book和映射BookSummary到此表。

首先,我们将创建一个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;
    }
}

现在,BookSummary实体只是扩展了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);
    }
}

持久实体

这样,您可以持久化任一Book实体:

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\"" +
            "}"
        )
);

BookSummary

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 book = entityManager
    .unwrap(Session.class)
    .bySimpleNaturalId(Book.class)
    .load("978-9730228236");
 
assertEquals(
    "High-Performance Java Persistence, 2nd edition",
    book.getTitle()
);

结论

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

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

于 2019-08-21T09:34:25.893 回答