Loading...

How to Define Association Mappings between Entities

View: 381    Dowload: 0   Comment: 0   Post by: hanhga   Category: Javascript   Fields: Other

In previous tutorial, we learned about four persistent states of hibernate entities and there we noted that hibernate can identify java objects as persistent only when they are annotated with certain annotations; otherwise they are treated as simple plain java objects with no direct relation to database. Moving on, when we annotate the java classes with JPA annotations and make them persistent entities, we can face situations where two entities can be related and must be referenced from each other, in either uni-direction or in bi-direction. Let’s understand few basic things before actually creating references between hibernate entities.

Understanding Entities and Their Associations

Entities can contain references to other entities, either directly as an embedded property or field, or indirectly via a collection of some sort (arrays, sets, lists, etc.). These associations are represented using foreign key relationships in the underlying tables. These foreign keys will rely on the identifiers used by participating tables.

When only one of the pair of entities contains a reference to the other, the association is unidirectional. If the association is mutual, then it is referred to as bidirectional.

Ideally, we would like to dictate that only changes to one end of the relationship will result in any updates to the foreign key; and indeed, Hibernate allows us to do this by marking one end of the association as being managed by the other.

In hibernate mapping associations, one (and only one) of the participating classes is referred to as “managing the relationship” and other one is called “managed by” using ‘mappedBy’ property. We should not make both ends of association “managing the relationship”. Never do it.

Understanding Associations with Example

Let’s quickly build and example to understand what we have read above about associations about entities and how this should be done. I am using two simple entities (AccountEntity and EmployeeEntity) for this example and then I will create one-to-one association between them. Then we will see how various association options change the runtime behavior and complexity.

AccountEntity.java

@Entity
@Table(name = "Account")
public class AccountEntity implements Serializable
{
   private static final long serialVersionUID = 1L;
 
   @Id
   @Column(name = "ID", unique = true, nullable = false)
   @GeneratedValue(strategy = GenerationType.SEQUENCE)
   private Integer           accountId;
 
   @Column(name = "ACC_NO", unique = false, nullable = false, length = 100)
   private String            accountNumber;
 
   //We will define the association here
   EmployeeEntity            employee;
 
   //Getters and Setters are not shown for brevity
}

EmployeeEntity.java.

@Entity
@Table(name = "Employee")
public class EmployeeEntity implements Serializable
{
   private static final long serialVersionUID = -1798070786993154676L;
   @Id
   @Column(name = "ID", unique = true, nullable = false)
   @GeneratedValue(strategy = GenerationType.SEQUENCE)
   private Integer           employeeId;
   @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
   private String            firstName;
   @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
   private String            lastName;
 
   //We will define the association here
   AccountEntity             account;
 
   //Getters and Setters are not shown for brevity
}

Scenario 1) Association managed by both entities

In this type of association, we will define the association as below using @OneToOne annotation.

//Inside EmployeeEntity.java
@OneToOne
AccountEntity       account;
 
//Inside AccountEntity.java
@OneToOne
EmployeeEntity      employee;

With above association, both ends are managing the association so both must be updated with information of each other using setter methods defined in entity java files. If you fail to do so, you will not be able to fetch the associated entity information and it will be returned as null.

public class TestHibernate
{
   public static void main(String[] args)
   {
      Session sessionOne = HibernateUtil.getSessionFactory().openSession();
      sessionOne.beginTransaction();
 
      // Create new Employee object
      EmployeeEntity emp = new EmployeeEntity();
      emp.setFirstName("Lokesh");
      emp.setLastName("Gupta");
 
      // Create new Employee object
      AccountEntity acc = new AccountEntity();
      acc.setAccountNumber("DUMMY_ACCOUNT");
      emp.setAccount(acc);
      //acc.setEmployee(emp);
 
      sessionOne.save(acc);
      sessionOne.save(emp);
      sessionOne.getTransaction().commit();
 
      Integer genEmpId = emp.getEmployeeId();
      Integer genAccId  = acc.getAccountId();
 
      Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
      sessionTwo.beginTransaction();
      EmployeeEntity employee = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId);
      AccountEntity account = (AccountEntity) sessionTwo.get(AccountEntity.class, genAccId);
 
      System.out.println(employee.getEmployeeId());
      System.out.println(employee.getAccount().getAccountNumber());
      System.out.println(account.getAccountId());
      System.out.println(account.getEmployee().getEmployeeId());
 
      HibernateUtil.shutdown();
   }
}
 
Output:
 
Hibernate: insert into Account (ACC_NO, employee_ID, ID) values (?, ?, ?)
Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?)
Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_,
            employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_,
            accountent1_.employee_ID as employee3_0_1_, employeeen2_.ID as ID1_1_2_, employeeen2_.account_ID as account_4_1_2_,
            employeeen2_.FIRST_NAME as FIRST_NA2_1_2_, employeeen2_.LAST_NAME as LAST_NAM3_1_2_ from Employee
            employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID
            left outer join Employee employeeen2_ on accountent1_.employee_ID=employeeen2_.ID where employeeen0_.ID=?
 
20
DUMMY_ACCOUNT
10
Exception in thread "main" java.lang.NullPointerException
    at com.howtodoinjava.test.TestHibernate.main(TestHibernate.java:43)

You see that I had set the account entity in employee entity, so I am able to get it. BUT I commented the line “acc.setEmployee(emp);” and thus not set the employee entity inside account entity, so I am not able to get it.

Also observe the insert queries above. Both tables have foreign key association with column names employee_ID andaccount_ID respectively. It’s example of circular dependency in data and can easily bring down your application any time.

To correctly store above relationship, you must un-comment the line “acc.setEmployee(emp);“. After uncommenting the line, you will be able to store and retrieve the association as desired but still there is circular dependency.

After uncommenting the line, output will be like below:

Hibernate: insert into Account (ACC_NO, employee_ID, ID) values (?, ?, ?)
Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?)
Hibernate: update Account set ACC_NO=?, employee_ID=? where ID=?
Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_,
            employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_,
            accountent1_.employee_ID as employee3_0_1_, employeeen2_.ID as ID1_1_2_, employeeen2_.account_ID as account_4_1_2_,
            employeeen2_.FIRST_NAME as FIRST_NA2_1_2_, employeeen2_.LAST_NAME as LAST_NAM3_1_2_ from Employee
            employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID
            left outer join Employee employeeen2_ on accountent1_.employee_ID=employeeen2_.ID where employeeen0_.ID=?
 
20
DUMMY_ACCOUNT
10
20

Scenario 2) Association managed by single entity

Let’s say association is managed by EmployeeEntity then the annotations in both entity will look like below.

//Inside EmployeeEntity.java
@OneToOne
AccountEntity       account;
 
//Inside AccountEntity.java
@OneToOne (mappedBy = "account")
EmployeeEntity      employee;

Now to tell hibernate the association is managed by EmployeeEntity, we will add ‘mappedBy‘ attribute insideAccountEntity to make it manageable. Now to test above code we will have to set the association only once using “emp.setAccount(acc);” and employee entity is which is managing the relationship. AccountEntity dos not need to know anything explicitly.

Let’s look at below test run.

Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();
 
// Create new Employee object
EmployeeEntity emp = new EmployeeEntity();
emp.setFirstName("Lokesh");
emp.setLastName("Gupta");
 
// Create new Employee object
AccountEntity acc = new AccountEntity();
acc.setAccountNumber("DUMMY_ACCOUNT");
emp.setAccount(acc);
//acc.setEmployee(emp);
 
sessionOne.save(acc);
sessionOne.save(emp);
sessionOne.getTransaction().commit();
 
Integer genEmpId = emp.getEmployeeId();
Integer genAccId  = acc.getAccountId();
 
Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
sessionTwo.beginTransaction();
EmployeeEntity employee = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId);
AccountEntity account = (AccountEntity) sessionTwo.get(AccountEntity.class, genAccId);
 
System.out.println(employee.getEmployeeId());
System.out.println(employee.getAccount().getAccountNumber());
System.out.println(account.getAccountId());
System.out.println(account.getEmployee().getEmployeeId());
 
HibernateUtil.shutdown();
 
Output:
 
Hibernate: insert into Account (ACC_NO, ID) values (?, ?)
Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?)
Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_,
employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_ from Employee employeeen0_
left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID where employeeen0_.ID=?
Hibernate: select employeeen0_.ID as ID1_1_1_, employeeen0_.account_ID as account_4_1_1_, employeeen0_.FIRST_NAME as FIRST_NA2_1_1_,
employeeen0_.LAST_NAME as LAST_NAM3_1_1_, accountent1_.ID as ID1_0_0_, accountent1_.ACC_NO as ACC_NO2_0_0_ from Employee employeeen0_
left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID where employeeen0_.account_ID=?
 
20
DUMMY_ACCOUNT
10
20

You see that you do not need to tell anything to account entity (‘acc.setEmployee(emp)‘ is commented). Employee entity is managing the association both ways.

Another observation is regarding foreign key columns which we have only one now i.e. account_ID is Employee table. So no circular dependency as well. All good.

Guide to Define Associations for Various Mappings

Above example shows how to manage association between entities in one-to-one mapping. In above example, we could have chosen the association managed by AccountEntity as well and things would have worked out pretty well with minor code changes. But in case of other mappings (e.g. One-to-many or Many-to-one), you will not have the liberty to define associations at your will. You need rules.

Below table shows how you can select the side of the relationship that should be made the owner of a bi-directional association. Remember that to make an association the owner, you must mark the other end as being mapped by the other.

[su_table]

TYPE OF ASSOCIATION OPTIONS/ USAGE
One-to-one Either end can be made the owner, but one (and only one) of them should be; if you don’t specify this, you will end up with a circular dependency.
One-to-many The many end must be made the owner of the association.
Many-to-one This is the same as the one-to-many relationship viewed from the opposite perspective, so the same rule applies: the many end must be made the owner of the association.
Many-to-many Either end of the association can be made the owner.

If this all seems rather confusing, just remember that association ownership is concerned exclusively with the management of the foreign keys in the database and that’s it. I will advise you to go through my previous tutorials discussing “one-to-one mapping“, “one-to-many mapping” and “many-to-many mapping” in details. They will help you in building the concept stronger.

How to Define Association Mappings between Entities

In previous tutorial, we learned about four persistent states of hibernate entities and there we noted that hibernate can identify java objects as persistent only when they are annotated with certain annotations

Posted on 06-08-2016 

Comment:

To comment you must be logged in members.

Files with category

  • Mini Youtube Using ReactJS

    Mini Youtube Using ReactJS

    View: 237    Download: 3   Comment: 0

    Category: Javascript     Fields: none

    This is one the best starter for ReactJS. MiniYoutube as the name suggests is a youtube like website developed using reactJS and youtube API. This project actually let's you search , play and list youtube videos. Do check it out and start learning...

  • AngularJS and REST API

    AngularJS and REST API

    View: 369    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    This is a tutorial for those interested in a quick introduction to AngularJS and REST API. We will build the familiar Periodic Table of the Elements found in every chemistry textbook, and allow the user to select a Chemical Element by clicking on...

  • Collective Intelligence, Recommending Items Based on Similar Users' Taste

    Collective Intelligence, Recommending Items Based on Similar Users' Taste

    View: 301    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Using Collaborative Filtering to find people who share tastes, and for making automatic recommendations based on things that other people like.

  • Think Like a Bird for Better Parallel Programming

    Think Like a Bird for Better Parallel Programming

    View: 278    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Coding an application to run in parallel is hard, right? I mean, it must be hard or we’d see parallel programs everywhere. All we'd see are slick parallel apps that use every available core effortlessly. Instead multi-threaded apps are the exception...

  • Getting Started with the Bing Search APIs

    Getting Started with the Bing Search APIs

    View: 302    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Bing Search API is a set of REST interfaces that find web pages, news, images, videos, entities, related searches, spelling corrections, and more in response to queries from any programming language that can generate a web request. Applications that...

  • Brief Introduction of SocketPro High Performance and Scalable Persistent Message Queue

    Brief Introduction of SocketPro High Performance and Scalable Persistent Message Queue

    View: 676    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Continuous in-line request/result batching, real-time stream sending/processing, asynchronous data transferring and parallel computation for best performance and scalability

  • Iteration Over Java Collections with High Performance

    Iteration Over Java Collections with High Performance

    View: 279    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Java developers usually deal with Collections such as ArrayList, HashSet, Java 8 come with lambda and streaming API helps us to easily work with Collections. In most cases, we work with few thousands of items and performance isn't a concern. But in...

  • SR2JLIB - A Symbolic Regression Library for Java

    SR2JLIB - A Symbolic Regression Library for Java

    View: 282    Download: 0   Comment: 0

    Category: Javascript     Fields: Other

    Grammar-Guided Genetic Programming library featuring: multi-threading, just-in-time compilation of individuals, dynamic class loading, and JNI interfacing with C/C++ code

 
File suggestion for you
Loading...
File top downloads
Loading...
Loading...
Codetitle - library source code to share, download the file to the community
Copyright © 2018. All rights reserved. codetitle Develope by Vinagon .Ltd