【问题标题】:Unidirectional association with type in join table与连接表中的类型的单向关联
【发布时间】:2013-12-26 03:47:30
【问题描述】:

我有 3 个表:Person -> Person_Address_Type {person_address_type_id(PK), person_id, address_id, type} -> 地址。 Person_Address_Type 是表示Person 和address 之间关系的类型。例如:

Mr. A has unique HOME addresses.
Mr. A has one or many OFFICE addresses.
Mr. A has one or many RELAXING addresses.
... And other types of address may be added later.

如何使用 Hibernate 进行映射以具有以下 java 实体:

Person {
     getHomeAddress(): Address;
     getOfficeAddresses(): Address*;
     getRelaxingAddresses(): Address*;
}

我知道有瞬态场。但是,我们不能使用瞬态进行 HQL 查询。我需要一个映射。 我怎样才能做到?

谢谢

【问题讨论】:

    标签: java hibernate mapping entity-relationship


    【解决方案1】:

    你的映射应该是这样的

    表结构

    CREATE TABLE `person` (
        `id_person` BIGINT(20) NOT NULL AUTO_INCREMENT,
        `firstname` VARCHAR(50) NULL DEFAULT NULL,
        `lastname` VARCHAR(50) NULL DEFAULT NULL,
        `birth_date` DATE NULL DEFAULT NULL,
        `cell_phone` VARCHAR(15) NULL DEFAULT NULL,
        PRIMARY KEY (`id_person`)
    )ENGINE=InnoDB;
    
    CREATE TABLE `address_type` (
        `id_address_type` BIGINT(10) NOT NULL AUTO_INCREMENT,
        `name` VARCHAR(50) NULL DEFAULT NULL,   
        PRIMARY KEY (`id_address_type`)
    )ENGINE=InnoDB;
    
    CREATE TABLE `address` (
        `id_address` BIGINT(10) NOT NULL AUTO_INCREMENT,
        `fk_address_type`BIGINT(20) NULL DEFAULT NULL,
        PRIMARY KEY (`id_address`),
        CONSTRAINT `FK_ADDRESS_TYPE` FOREIGN KEY (`fk_address_type`) REFERENCES `address_type` (`id_address_type`),
    )ENGINE=InnoDB;
    
    CREATE TABLE `person_address` (
        `id_person_address` BIGINT(10) NOT NULL AUTO_INCREMENT, 
        `fk_person` BIGINT(20) NULL DEFAULT NULL,
        `fk_address`BIGINT(20) NULL DEFAULT NULL,       
        PRIMARY KEY (`id_person_address`),
        CONSTRAINT `FK_PERSON` FOREIGN KEY (`fk_person`) REFERENCES `person` (`id_person`),
        CONSTRAINT `FK_ADDRESS` FOREIGN KEY (`fk_address`) REFERENCES `address` (`id_address`)  
    )ENGINE=InnoDB;
    

    实体类

    Person.java

    @Entity
    @Table(name = "person",uniqueConstraints = {
    @UniqueConstraint(columnNames = "id_person")})
    public class Person implements Serializable {
        private static final long serialVersionUID = -1798070786993154676L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id_person", unique = true, nullable = false)
        private Integer id;
    
        @OneToMany(cascade=CascadeType.ALL)
        @JoinTable(name="person_address", joinColumns={@JoinColumn(name="fk_person", referencedColumnName="id_person")}
        , inverseJoinColumns={@JoinColumn(name="fk_address", referencedColumnName="id_address")})
        private Set<Address> address;
    
       // Getter and Setter methods 
    }
    

    Address.java

    @Entity
    @Table(name = "address", uniqueConstraints = {
    @UniqueConstraint(columnNames = "id_address")})
    public class Address implements Serializable {
    
        private static final long serialVersionUID = -6790693372846798580L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id_address", unique = true, nullable = false)
        private Integer addressId;
    
        @OneToOne(mappedBy="address", cascade=CascadeType.ALL)
        private AddressType addressType;    
    
       // Getter and Setter methods
    }
    

    AddressType.java

    @Entity
    @Table(name="address_type",uniqueConstraints = {
    @UniqueConstraint(columnNames = "id_address_type")})
    public class AddressType {
         
        @Id
        @Column(name="id_address_type", unique=true, nullable=false)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long addressTypeId;
    
    
    
        @OneToOne
        @PrimaryKeyJoinColumn
        private Address address;    
    
        // Getter and Setter methods
    }
    

    现在,当您调用 getAddress() 时,这将返回与 Person 相关的所有地址,然后根据地址类型对该地址进行分组,即通过调用 address.getAddressType().getName() 方法。

    您还可以在 Address 和 AddressType 实体之间进行@ManyToMany 映射

    【讨论】:

    • 对不起。我想看到的最重要的地图是 Person 类中的 getter(getHomeAddress(): getOfficeAddresses(): Address*...)。然而,他们不在这里。
    【解决方案2】:

    从我对 Hibernate 的基本了解来看,Hibernate 似乎不直接支持关系表的样式。

    最简单的方法是为您的Person_Address_Type 创建单独的视图,这样您就有 3 个关系表,例如:PERSON_HOME_ADDRESSPERSON_OFFICE_ADDRESSPERSON_RELAX_ADDRESS 等。

    每个视图只包含PERSON_IDADDRESS_ID

    有了这些视图,你就可以用JoinTable做一个普通的ManyToMany/ManyToOne

    但是,如果您想直接使用这些实体更新关系,这种方法可能不起作用(取决于 DBMS,某些 DBMS 允许通过视图进行更新/插入)。

    另一种方法是创建一个新实体,例如 PersonAddressRelationship,其中包含对 Person、Address 和一个 RelationshipType 枚举的引用。

    那么Person to Address中的三个关系不是直接映射的。相反,您根据映射的addressRelationships@PostLoad 方法中填充homeAddressrelaxAddressesofficeAddresses 的值。 (并在 @PrePersist 方法中基于 homeAddressrelaxAddressesofficeAddresses 更新 addressRelationships

    【讨论】:

      【解决方案3】:

      我刚刚发现@WhereJoinTable 是为此而生的(只是理论上,我没有在实践中尝试过)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多