// you're reading...

EJB3 JPA Entity Many-To-One Relationship

A Many-To-One relationship is whereby one object class is “part of” or being consisted in many other object classes. Where can you discover many-To-One relationship? Usually it appears the moment when you perform a website registration whereby you have to select your country details from a drop down box when the website ask for your profile and address details, this is when many user records shares the same record of country and states.


Today, let us take a look at how to store property information in the real industry. Regardless of whatever property the real estate firm sells, properties will still be categorized as apartments, condominiums, link houses, bungalows, land, SOHO, etc. Therefore, every property info will consists of a singular property type.

The below are the database table diagram and the SQL codes to generate the table structure in MySQL.

 SQL |  copy code |? 
01
CREATE TABLE APP_PROPERTY_TYPES
02
(
03
    APP_PT_PK INT NOT NULL AUTO_INCREMENT,
04
    PROPERTY_TYPE VARCHAR(255) NOT NULL,
05
    PRIMARY KEY(APP_PT_PK),
06
    UNIQUE(PROPERTY_TYPE)
07
);
08
 
09
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Apartment');
10
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Condominium');
11
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Terrace House');
12
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Semi-D House');
13
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Bungalow');
14
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Residential Land');
15
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Industrial Land');
16
INSERT INTO APP_PROPERTY_TYPES(PROPERTY_TYPE) VALUES ('Commercial Land');
17
 
18
CREATE TABLE APP_PROPERTIES
19
(
20
    APP_PROPERTIES_PK BIGINT NOT NULL AUTO_INCREMENT,
21
    PROPERTY_ADDRESS_STR VARCHAR(255) NOT NULL,
22
    PROPERTY_TYPE_PK INT NOT NULL,
23
    PROPERTY_DESC TEXT,
24
    OWNER_FULLNAME VARCHAR(255) NOT NULL,
25
    OWNER_CONTACT VARCHAR(255) NOT NULL,
26
    SELLING_PRICE DECIMAL(12, 2) NOT NULL,
27
    PRIMARY KEY(APP_PROPERTIES_PK),
28
    FOREIGN KEY(PROPERTY_TYPE_PK) REFERENCES APP_PROPERTY_TYPES(APP_PT_PK) ON UPDATE CASCADE ON DELETE RESTRICT
29
);

The APP_PROPERTIES table will contain the records of different types that are available for sale. For the property type info, it just links to the APP_PROPERTY_TYPE table through the foreign key field of APP_PROPERTIES.PROPERTY_TYPE_PK. APP_PROPERTY_TYPE table will consists static records of property types, which will be used by many APP_PROPERTIES records.

As for the Java classes, the below are the codes for both PropertyEntity class which encapsulates the structure in the APP_PROPERTIES table and PropertyTypeEntity, which encapsulates the structure in APP_PROPERTY_TYPES table.

Codes for PropertyEntity class:

 Java(TM) 2 Platform Standard Edition 5.0 |  copy code |? 
001
package com.developerscrappad.propmng.entity;
002
 
003
import java.io.Serializable;
004
import javax.persistence.Basic;
005
import javax.persistence.Column;
006
import javax.persistence.Entity;
007
import javax.persistence.GeneratedValue;
008
import javax.persistence.GenerationType;
009
import javax.persistence.Id;
010
import javax.persistence.JoinColumn;
011
import javax.persistence.ManyToOne;
012
import javax.persistence.Table;
013
 
014
@Entity
015
@Table(name = "APP_PROPERTIES")
016
public class PropertyEntity implements Serializable {
017
 
018
    private static final long serialVersionUID = 6397311185164388570L;
019
 
020
    @Id
021
    @GeneratedValue(strategy = GenerationType.IDENTITY)
022
    @Column(name = "APP_PROPERTIES_PK")
023
    private Long appPropertiesPk;
024
 
025
    @Basic(optional = false)
026
    @Column(name = "PROPERTY_ADDRESS_STR")
027
    private String propertyAddressStr;
028
 
029
    @Column(name = "PROPERTY_DESC")
030
    private String propertyDesc;
031
 
032
    @Column(name = "OWNER_FULLNAME")
033
    private String ownerFullname;
034
 
035
    @Column(name = "OWNER_CONTACT")
036
    private String ownerContact;
037
 
038
    @Column(name = "SELLING_PRICE")
039
    private Double sellingPrice;
040
 
041
    @JoinColumn(name = "PROPERTY_TYPE_PK", referencedColumnName = "APP_PT_PK")
042
    @ManyToOne(optional = false)
043
    private PropertyTypeEntity propertyType;
044
 
045
    public PropertyEntity() {
046
    }
047
 
048
    public PropertyEntity(Long appPropertiesPk) {
049
        this.appPropertiesPk = appPropertiesPk;
050
    }
051
 
052
    public PropertyEntity(Long appPropertiesPk, String propertyAddressStr, String ownerFullname, String ownerContact, Double sellingPrice, PropertyTypeEntity propertyType) {
053
        this.appPropertiesPk = appPropertiesPk;
054
        this.propertyAddressStr = propertyAddressStr;
055
        this.ownerFullname = ownerFullname;
056
        this.ownerContact = ownerContact;
057
        this.sellingPrice = sellingPrice;
058
        this.propertyType = propertyType;
059
    }
060
 
061
    public Long getAppPropertiesPk() {
062
        return appPropertiesPk;
063
    }
064
 
065
    public void setAppPropertiesPk(Long appPropertiesPk) {
066
        this.appPropertiesPk = appPropertiesPk;
067
    }
068
 
069
    public String getPropertyAddressStr() {
070
        return propertyAddressStr;
071
    }
072
 
073
    public void setPropertyAddressStr(String propertyAddressStr) {
074
        this.propertyAddressStr = propertyAddressStr;
075
    }
076
 
077
    public String getPropertyDesc() {
078
        return propertyDesc;
079
    }
080
 
081
    public void setPropertyDesc(String propertyDesc) {
082
        this.propertyDesc = propertyDesc;
083
    }
084
 
085
    public String getOwnerFullname() {
086
        return ownerFullname;
087
    }
088
 
089
    public void setOwnerFullname(String ownerFullname) {
090
        this.ownerFullname = ownerFullname;
091
    }
092
 
093
    public String getOwnerContact() {
094
        return ownerContact;
095
    }
096
 
097
    public void setOwnerContact(String ownerContact) {
098
        this.ownerContact = ownerContact;
099
    }
100
 
101
    public void setSellingPrice(Double sellingPrice) {
102
        this.sellingPrice = sellingPrice;
103
    }
104
 
105
    public Double getSellingPrice() {
106
        return sellingPrice;
107
    }
108
 
109
    public PropertyTypeEntity getPropertyType() {
110
        return propertyType;
111
    }
112
 
113
    public void setPropertyType(PropertyTypeEntity propertyType) {
114
        this.propertyType = propertyType;
115
    }
116
 
117
    @Override
118
    public int hashCode() {
119
        int hash = 0;
120
        hash += (appPropertiesPk != null ? appPropertiesPk.hashCode() : 0);
121
        return hash;
122
    }
123
 
124
    @Override
125
    public boolean equals(Object object) {
126
        // TODO: Warning - this method won't work in the case the id fields are not set
127
        if (!(object instanceof PropertyEntity)) {
128
            return false;
129
        }
130
        PropertyEntity other = (PropertyEntity) object;
131
        if ((this.appPropertiesPk == null && other.appPropertiesPk != null) || (this.appPropertiesPk != null && !this.appPropertiesPk.equals(other.appPropertiesPk))) {
132
            return false;
133
        }
134
        return true;
135
    }
136
 
137
    @Override
138
    public String toString() {
139
        return "com.developerscrappad.propmng.entity.PropertiesEntity[ appPropertiesPk=" + appPropertiesPk + " ]";
140
    }
141
}

Codes for PropertyTypeEntity class:

 Java(TM) 2 Platform Standard Edition 5.0 |  copy code |? 
01
package com.developerscrappad.propmng.entity;
02
 
03
import java.io.Serializable;
04
import javax.persistence.Column;
05
import javax.persistence.Entity;
06
import javax.persistence.GeneratedValue;
07
import javax.persistence.GenerationType;
08
import javax.persistence.Id;
09
import javax.persistence.Table;
10
 
11
@Entity
12
@Table(name = "APP_PROPERTY_TYPES")
13
public class PropertyTypeEntity implements Serializable {
14
 
15
    private static final long serialVersionUID = 2223674512837985849L;
16
 
17
    @Id
18
    @GeneratedValue(strategy = GenerationType.IDENTITY)
19
    @Column(name = "APP_PT_PK")
20
    private Integer appPtPk;
21
 
22
    @Column(name = "PROPERTY_TYPE")
23
    private String propertyType;
24
 
25
    public PropertyTypeEntity() {
26
    }
27
 
28
    public PropertyTypeEntity(Integer appPtPk) {
29
        this.appPtPk = appPtPk;
30
    }
31
 
32
    public PropertyTypeEntity(Integer appPtPk, String propertyType) {
33
        this.appPtPk = appPtPk;
34
        this.propertyType = propertyType;
35
    }
36
 
37
    public Integer getAppPtPk() {
38
        return appPtPk;
39
    }
40
 
41
    public void setAppPtPk(Integer appPtPk) {
42
        this.appPtPk = appPtPk;
43
    }
44
 
45
    public String getPropertyType() {
46
        return propertyType;
47
    }
48
 
49
    public void setPropertyType(String propertyType) {
50
        this.propertyType = propertyType;
51
    }
52
 
53
    @Override
54
    public int hashCode() {
55
        int hash = 0;
56
        hash += (appPtPk != null ? appPtPk.hashCode() : 0);
57
        return hash;
58
    }
59
 
60
    @Override
61
    public boolean equals(Object object) {
62
        // TODO: Warning - this method won't work in the case the id fields are not set
63
        if (!(object instanceof PropertyTypeEntity)) {
64
            return false;
65
        }
66
        PropertyTypeEntity other = (PropertyTypeEntity) object;
67
        if ((this.appPtPk == null && other.appPtPk != null) || (this.appPtPk != null && !this.appPtPk.equals(other.appPtPk))) {
68
            return false;
69
        }
70
        return true;
71
    }
72
 
73
    @Override
74
    public String toString() {
75
        return "com.developerscrappad.propmng.entity.PropertyTypeEntity[ appPtPk=" + appPtPk + " ]";
76
    }
77
}

In order to have a PropertyTypeEntity object being part of the PropertyEntity object, we mark the propertyType property in PropertyEntity class as @ManyToOne. Of course additionally, to instruct the app server how to properly tie the relationship is by having an annotation of @JoinColumn as well.

@JoinColumn(name = "PROPERTY_TYPE_PK", referencedColumnName = "APP_PT_PK")
@ManyToOne(optional = false)

In the @JoinColumn annotation, the name attribute always refers to the column of the foreign key in the table that the class represents. In this case, it is APP_PROPERTIES.PROPERTY_TYPE_PK. As for the referenceColumn attribute, the value should be the target reference column of the primary key field of the table that APP_PROPERTIES.PROPERTY_TYPE_PK references to. In this case, it is APP_PROPERTY_TYPES.APP_PT_PK.

Simple isn’t it? This sums up how we can code a Many-To-One relationship in our Java Entity classes.

Previous Posts

MySQL Cluster NDB 7.2 on Solaris 10 Part 3 – Testing The Cluster

MySQL Cluster NDB 7.2 on Solaris 10 Part 3 - Testing The Cluster

September 22nd, 2012

We are back again to have fun with our cluster that we've setup written in our previous articles on [...]

MySQL Cluster NDB 7.2 on Solaris 10 Part 2 – Starting, Distributed Synchronized Users Management And Stopping The Cluster

MySQL Cluster NDB 7.2 on Solaris 10 Part 2 - Starting, Distributed Synchronized Users Management And Stopping The Cluster

September 18th, 2012

This is the continuation from the previous part of the tutorial MySQL Cluster NDB 7.2 on Solaris 10 [...]

MySQL Cluster NDB 7.2 on Solaris 10 Part 1 – How To Install, Setup and Configure

MySQL Cluster NDB 7.2 on Solaris 10 Part 1 - How To Install, Setup and Configure

September 18th, 2012

If you have landed on this page, we believe you might either had a bumpy ride in getting the MySQL c[...]

Quick Fix: How to Solve “Unable to read the logging configuration” on Netbeans7 with JBoss6

Quick Fix: How to Solve "Unable to read the logging configuration" on Netbeans7 with JBoss6

September 8th, 2012

This is just a quick fix post for those whom are having this problem when running JBoss 6.x with Net[...]

Making sense of EJB3.x Transaction Attributes – Part 4 (NEVER)

Making sense of EJB3.x Transaction Attributes – Part 4 (NEVER)

September 5th, 2012

This is the last part in the series of "Making sense of EJB3.x Transaction Attributes". So far, we'v[...]

Making sense of EJB3.x Transaction Attributes – Part 3 (Difference Between SUPPORTS and NOT_SUPPORTED)

Making sense of EJB3.x Transaction Attributes – Part 3 (Difference Between SUPPORTS and NOT_SUPPORTED)

September 5th, 2012

Oracle had extensively documented the behavior of each transaction attributes in the Java EE documen[...]

Making sense of EJB3.x Transaction Attributes – Part 2 (MANDATORY)

Making sense of EJB3.x Transaction Attributes - Part 2 (MANDATORY)

April 17th, 2012

In my previous post, we've discussed about TransactionAttributeType.REQUIRES_NEW: how it behaves and[...]

Making sense of EJB3.x Transaction Attributes – Part 1 (REQUIRES_NEW)

Making sense of EJB3.x Transaction Attributes - Part 1 (REQUIRES_NEW)

March 29th, 2012

For the previous past posts, I have dealth much with manual fine-grind transaction, mostly on the su[...]

EJB3.x JPA: When to use rollback() and setRollbackOnly()

EJB3.x JPA: When to use rollback() and setRollbackOnly()

March 23rd, 2012

After JTA was introduced for more than a decade ago, then later with the introduction of Bean-Manage[...]