sql - Hibernate - 一张表多个实体

标签 sql hibernate

首先,我已阅读 Hibernate - One table with multiple entities? .

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

  • 一张表:Person(id、name、dateOfBirth、城市、街道、邮政编码)。
  • 两个实体:Person (id, name, dateOfBirth), Address (id, city,
    街道,邮政编码)。

  • 所以它是实体之间的 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数据库表:
    enter image description here
    映射实体
    现在,您可以映射两个实体:BookBookSummary到这张 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/

    相关文章:

    sql - ANSI SQL 使用 <> 作为比较运算符有什么原因吗?

    sql - 为什么 MySQL 从两个不同的查询中有效地输出数据?

    sql - 按周计算首次订阅者

    java - JPA - 为 SINGLE_TABLE 层次结构抽象类的两个子类分配不同的唯一约束

    java - 如何解决 "org.hibernate.QueryException: Not all named parameters have been set"错误?

    java - 需要帮忙! Spring 启动错误: Unsatisfied DependancyException: Error creating bean with name ''

    php - 选择数据并在所选记录中查找重复值的sql查询

    mysql - 将列中的最大值插入同一列?

    hibernate - 如何定义两个抽象类之间的 ManyToOne 关系

    java - 拦截 Hibernate 条件查询