首先,我已阅读 Hibernate - One table with multiple entities? .
但是,我想将两个实体映射到同一个表,但我希望它们都是实体,我可以从中进行选择。我的意思是:
街道,邮政编码)。
所以它是实体之间的 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 是数据库生成的)
Address ad = new Address();
ad.setProperty("Sydney");
Person p = new Person();
p.setProperty("John");
p.setAddress(ad);
session.save(p);
并且只保存了 Person 部分,address 属性保持为空。
最佳答案
使用 JPA 和 Hibernate 实现这一点非常简单。
假设您正在使用以下 book
数据库表:
映射实体
现在,您可以映射两个实体:Book
和 BookSummary
到这张 table 。
首先,我们将创建一个 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
父类(super class)并且不添加额外的实体属性。@Entity(name = "BookSummary")
@Table(name = "book")
public class BookSummary extends BaseBook<BookSummary> {
}
另一方面,Book
实体扩展了 BaseBook
父类(super class)并映射 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 必须检查更少的实体属性。
使用这种方法的唯一缺点是,您必须确保不会为同一个数据库表记录获取多个实体类型,否则,这可能会在刷新持久性上下文时导致不一致。
关于sql - Hibernate - 一张表多个实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18547932/