Unidirectional association with type in join table

I have 3 tables: Person -> Person_Address_Type {person_address_type_id(PK), person_id, address_id, type} -> Address. The Person_Address_Type is to indicate the type of the relationship between Person and addresses. For example:

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.

How can I make the mapping with Hibernate to have below java entity:

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

I know about having transient fields. However, we can't do HQL query with transient. I need a mapping. How can I make it?

Thanks

Answers


Your mapping should be like this

Table Structure

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;

Entity Classes

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
}

now when you call getAddress() this will return all the address related to Person then group this address according to there address type i.e. by calling address.getAddressType().getName() method.

You can also have @ManyToMany mapping between Address and AddressType entities


from my bare knowledge of Hibernate, seems that the style of relationship table is not directly supported in Hibernate.

The easiest way is to create separate views of your Person_Address_Type, so that you have 3 relationship tables like: PERSON_HOME_ADDRESS, PERSON_OFFICE_ADDRESS, PERSON_RELAX_ADDRESS etc.

Each of the view just contains PERSON_ID and ADDRESS_ID

With these views, you can do a normal ManyToMany/ManyToOne with JoinTable.

However this approach may not work if you want to update the relationships directly using these entities (depending on DBMS, some DBMS allow update/insert through views).

Another way is creating a new entity, like PersonAddressRelationship, which contains ref to Person, Address and a RelationshipType enum.

Then the three relationships in Person to Address is not directly mapped. Instead, you populate the value of homeAddress, relaxAddresses and officeAddresses in @PostLoad method, base on your mapped addressRelationships. (and update the addressRelationships base on homeAddress, relaxAddresses and officeAddresses in @PrePersist method too)


I have just found that @WhereJoinTable is for this (just in theory, I haven't tried in practice)


Need Your Help

Login site using casperJS

login phantomjs casperjs autofill

I am using casperJS to auto fill a form and test some functionality of the site.

How to delete the only cell from UICollectionView with animation (deleteItemsAtIndexPaths)?

ios objective-c uicollectionview uicollectionviewcell

I'm getting an assertion while deleting a single UICollecitonViewCell from UICollectionView.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.