JavaData & JavaHow to Implement Database Relationship in Hibernate

How to Implement Database Relationship in Hibernate

The crux of the relational database management system is in the idea of establishing relationship among entities. We establish this relationship in a database with the help of DDL SQL join, foreign keys, etc. With Hibernate and EJB persistence specification we can easily model association between entities. In this article we shall use this ability to model association between entities from Java code, without bothering about the SQL.

Relationship

Database relationship has a very concrete mathematical foundation in classical database literature. To make it simple, we keep aside its mathematical counterpart and try to understand the same analogically.

Entities are the key players of any system – for example in a school, teachers, students, and classrooms are entities. In much the same way, in an organization employees, managers, projects, and departments are entities. These entities obviously have some relationship among them such as:

Employees [ works for ] a department
Employees [ works on ] a project

Now, if Employee is an entity then ‘John Smith’, for example, is an instance of that entity. So Employee is nothing but an abstraction of a real entity with some unique attributes. Each abstraction creates a relation/table in the database. And each table has a collection of such instances called records.

records

Now a collection of several such instances make a relation or table.

But while creating relationships among separate entities, we need to specify the number of times that an entity can participate in a relationship instance. This is called degree of relationship or cardinality ratios. There are three types of relationship degrees:

  • One-to-One (1:1) – one employee works for one department.
  • One-to-Many (1:N) or Many-to-One (N:1) depending upon from which perspective we are looking at the relationship. One employee works in many projects.
  • Many-to-Many (N:M) – Many books are written by many authors.

Mapping Model Class into Database Tables

In hibernate we can map a model object into a relation/table with the help of @Entity annotation. The member variables of the model object corresponds to the table attributes. The table attributes in this case are Java primitive types, which maps into corresponding database specific primitive types. @Id defines a primary key into the database and @GeneratedValue specifies that this primary key would be auto generated by the database.

@Entity
public class Employee{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)         
    private long empId;
    private String empName;    
    private String address;
    private String sex;
    private float salary;    
…
}

EmpId (PK)

EmpName

Sex

salary

123456789

John Smith

Male

45000

Mapping Embedded Objects

In a situation where the member variable of a model object is another object itself, then this encapsulated object is merged into the embedded model class. The @Embedded and @Embeddable annotation are used to manage this type of relationship.

@Entity
public class Employee{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long empId;
    private String empName;    
    @Embedded
    private Address address;
    private String sex;
    private float salary;    
…
}
 
@Embeddable
public class Employee{
    private String street;
    private String province;    
    private String country;
    private String zip;
…
}

EmpId (PK)

EmpName

street

zip

salary

123456789

John Smith

45000

One-to-One Association

To establish a one-to-one association between two separate object models we use @OneToOne annotation as follows. Here in this example we assume that each employee works in one department, so the cardinality ratio of the relationship is 1:1.

@Entity
public class Employee{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long empId;    
…
   @OneToOne
   private Department department;
}
 
@Entity
public class Department{
    @Id  @GeneratedValue
    private long empId;    
…   
}

One-to-Many or Many-to-One Association

One-to-Many or Many-to-One association are basically same, seen from alternate perspectives of owning and subordinate entities. The annotation used for this type of relationship is @OneToMany. In the example below we assume that each employee can work in more than one project, so the degree of relationship is 1:N.

@Entity
public class Employee{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long empId;    
…
   @OneToMany
   private Collection<Project> projects=new ArrayList<>();
}
 
@Entity
public class Project{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long projectId;    
…
}

In this case what Hibernate does is that it creates a separate table with a primary key denoted by @Id in model class and uses it to map the attributes in the database table.

Employee

EmpId (PK)

EmpName

salary

123456789

John Smith

45000

Project

projectId (PK)

startDate

123456789

2/2/2012

New Table: Employee_Project

EmpId

projectId

Further if we want, we can also make a reverse relationship from Project to Employee by making the following changes in the Project class.

@Entity
public class Project{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long projectId;    
…
   @ManyToOne
   private Employee employee;
}

Many-to-Many Association

When more than one entity instance is associated with multiple instances of a separate entity, The relation degree becomes N:M. This type of relationship is established in Hibernate with the help of @ManyToMany annotation. For example, the relationship between Book and Author; more than one author may write one or more books; alternatively, many books are written by one or more author.

@Entity
public class Book{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long isbn;    
…
   @ManyToMany(mappedBy=”books”)   
   private Collection<Author> authors=new ArrayList<>();
}
 
@Entity
public class Author{
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private long authorId;    
…   
@ManyToMany
   private Collection<Book> books=new ArrayList<>();
}

A Sample Application

The Java code below demonstrates all three types of relationships.

relationships

Book.java

//...import statements
 
@Entity
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String isbn;
    private String title;
    @OneToOne
    private Publisher publisher;
    @OneToMany
    private Collection<Category> categories=new ArrayList<>();
    @ManyToMany
    private Collection<Author> authors=new ArrayList<>();
 
//...getters and setters
 
}

Publisher.java

//...import statements
 
@Entity
public class Publisher implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String publisherName;
    @Embedded
    private Address publisheAddress;
 
  //... getters and setters      
}

Address.java

//...import statements
 
@Embeddable
public class Address implements Serializable {
    private String street;
    private String province;
    private String zip;
    private String email;    
    private String phone;
 
 //... getters and setters
}

Authors.java

//...import statements
 
@Entity
public class Author implements Serializable {
 
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String authorName;
    private String bio;
    @ManyToMany(mappedBy = "authors")
    private Collection<Book> books = new ArrayList<>();
 
   //... getters and setters
}

Category.java

//...import  statements
 
@Entity
public class Category implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String categoryName;
    private String description;
 
//... getters and setters
 
}

HibernateUtil.java

//...import statements
 
public class HibernateUtil {
     private static final  SessionFactory sessionFactory;
     private static final  ServiceRegistry serviceRegistry;
     static {
          try {
               Configuration config = getConfiguration();
               serviceRegistry = new ServiceRegistryBuilder().applySettings(
                         config.getProperties()).buildServiceRegistry();
               config.setSessionFactoryObserver(new SessionFactoryObserver() {
                    private static final long  serialVersionUID = 1L;
 
                    @Override
                    public void sessionFactoryCreated(SessionFactory factory) {
                    }
 
                    @Override
                    public void sessionFactoryClosed(SessionFactory factory) {
                         ServiceRegistryBuilder.destroy(serviceRegistry);
                    }
               });
               sessionFactory = config.buildSessionFactory(serviceRegistry);
          } catch (Throwable ex) {
               System.err.println("Initial SessionFactory creation failed." + ex);
               throw new ExceptionInInitializerError(ex);
          }
     }
 
     public static  Session openSession() {
          return sessionFactory.openSession();
     }
 
     private static  Configuration getConfiguration() {
          Configuration cfg = new Configuration();
          cfg.addAnnotatedClass(Book.class );
          cfg.addAnnotatedClass(Author.class );
          cfg.addAnnotatedClass(Category.class );
          cfg.addAnnotatedClass(Publisher.class );
          cfg.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver");
          cfg.setProperty("hibernate.connection.url","jdbc:mysql://localhost:3306/mydatabase?zeroDateTimeBehavior=convertToNull");
          cfg.setProperty("hibernate.connection.username", "user1");
          cfg.setProperty("hibernate.connection.password", "secret");
          cfg.setProperty("hibernate.show_sql", "true");
          cfg.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
          cfg.setProperty("hibernate.hbm2ddl.auto", "create-drop");
          cfg.setProperty("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider");
          cfg.setProperty("hibernate.current_session_context_class", "thread");
          return cfg;
     }
}

MyLibrary.java

//...import statements
 
public class MyLibrary {
 
    public static void main(String[] args) {
        
        Book book=new Book();
        book.setIsbn("81-7808-137-7");
        book.setTitle("Fundamentals of Database System");
        
        Publisher pub=new Publisher();
        pub.setPublisherName("Pearson");
        
        Address add=new Address();
        add.setStreet("123 ABC Street");
        add.setProvince("XYZ");
        add.setPhone("9282736446");
        add.setEmail("info@pearson.com");
        add.setZip("1010101");
        
        pub.setPublisheAddress(add);
        
        book.setPublisher(pub);
        
        Author a1=new Author();
        a1.setAuthorName("Elmasri");
        a1.setBio("bio not available");
        
        Author a2=new Author();
        a2.setAuthorName("Navathe");
        a2.setBio("bio not available");
        
        book.getAuthors().add(a1);
        book.getAuthors().add(a2);
        
        Category c1=new Category();        
        c1.setCategoryName("Database");
        c1.setDescription("not Available");
        
        Category c2=new Category();
        c2.setCategoryName("Computer");
        c2.setDescription("not Available");
        
        book.getCategories().add(c1);
        book.getCategories().add(c2);
                
        
        Session session=HibernateUtil.openSession();
        session.beginTransaction();
        session.save(pub);
        session.save(a1);
        session.save(a2);
        session.save(c1);
        session.save(c2);
        session.save(book);
        session.getTransaction().commit();
        session.close();
    }
    
}

Conclusion

Establishing relationship in a database often requires one to write complex DDL SQL statements. Obviously, we do not even get a hint of such complexity while working with Hibernate. Hibernate also allows one to create relationships using the inheritance mechanism. In a way it provides a solution where database programmers need to learn only one language – Java. This is the power of this excellent ORM tool. 

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories