Persisting List

List is an interface provided by Java and accessed from java.util.List that has the capability to store a sequence of elements, allow duplicate elements, and contain elements of the same type. Some classes that implement the List interface are java.util.ArrayList, java.util.LinkedList, and so on. Now, let's look at how to use List while using hibernate.

Getting ready

Here, we consider a new table structure for employee, and each employee has multiple e-mail addresses. So, we create an Employee class that has the List<String> field e-mails called list of e-mail addresses. Here, we use the List class for this recipe. To achieve this, we need to create classes and tables; so, first of all, let's meet the basic prerequisites.

Creating tables

Use the following script to create the tables, unless you are using hbm2dll=create|update to dynamically create the table using hibernate.

Use the following code to create the employee table:

CREATE TABLE `employee` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Use the following code to create the email table:

CREATE TABLE `email` (
  `Employee_id` BIGINT(20) NOT NULL,
  `emails` VARCHAR(255) DEFAULT NULL,
  `email_index` INT(11) NOT NULL,
  PRIMARY KEY (`Employee_id`,`email_index`),
  KEY `FK5C24B9C37808516` (`Employee_id`),
  CONSTRAINT `FK5C24B9C37808516` FOREIGN KEY (`Employee_id`) REFERENCES `employee` (`id`)
);

Creating a class

Use the following code to create a class:

Source file: Employee.java

@Entity
@Table(name = "employee")
public class Employee {

  @Id
  @GeneratedValue
  @Column(name = "id")
  private long id;

  @Column(name = "name")
  private String name;

  @ElementCollection(fetch=FetchType.LAZY)
  @CollectionTable(name = "email")
  @IndexColumn(name="email_index")
  private List<String> emails;

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List<String> getEmails() {
    return emails;
  }

  public void setEmails(List<String> emails) {
    this.emails = emails;
  }

  @Override
  public String toString() {
    return "Employee"
        + "
	Id:" + this.id
        + "
	Name:" + this.name
        + "
	Emails:" + this.emails;
  }

}

How to do it…

In this section, we will take a look at how to insert, retrieve, delete, and update List, step by step.

Inserting a record

The following code is used to insert a record into the database. Here, we will try to insert the record of an employee with three e-mail addresses:

Code

  SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
  Session session = sessionFactory.openSession();

  Employee employee = new Employee();
  employee.setName("yogesh");
    
  List<String> emails = new ArrayList<String>();
  emails.add("[email protected]");
  emails.add("[email protected]");
  emails.add("[email protected]");
  employee.setEmails(emails);
    
  session.getTransaction().begin();
  session.save(employee);
  session.getTransaction().commit();

Output

Hibernate: insert into employee (name) values (?)
Hibernate: insert into email (Employee_id, email_index, emails) values (?,?,?)
Hibernate: insert into email (Employee_id, email_index, emails) values (?,?,?)
Hibernate: insert into email (Employee_id, email_index, emails) values (?,?,?)
Employee
  Id: 1
  Name: yogesh
  Emails: [[email protected], [email protected], [email protected]]

When this code is executed, it inserts one record into the employee table and three into the email table. It also sets a primary key value for the employee record in each record of the email table as a reference.

Retrieving a record

Here, we know that the record is inserted with id 1. So, we will try to get only this record and understand how List works.

Use the following code to retrieve the records of Employee#1:

Code

  Employee employee = (Employee) session.get(Employee.class, 1l);
  System.out.println(employee.toString());

Output

Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from employee employee0_ where employee0_.id=?
Hibernate: select emails0_.Employee_id as Employee1_0_0_, emails0_.emails as emails0_, emails0_.email_index as email3_0_ from email emails0_ where emails0_.Employee_id=?
Employee 
  Id: 1
  Name: yogesh
  Emails: [[email protected], [email protected], [email protected]]

Here, we notice that hibernate executes two different queries: one is to load the employee object and the other to load all the e-mail addresses referenced to that particular employee.

Updating a record

Here, we will try to add one more e-mail address to the list of e-mail IDs for Employee#1, which means that we will update the list of e-mails. Use the following code to do so:

Code

  Employee employee = (Employee) session.get(Employee.class, 1l);
  List<String> emails = employee.getEmails();
  emails.add("[email protected]");
  session.getTransaction().begin();
  session.saveOrUpdate(employee);
  session.getTransaction().commit();
   System.out.println(employee.toString());

Output

Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from employee employee0_ where employee0_.id=?
Hibernate: select emails0_.Employee_id as Employee1_0_0_, emails0_.emails as emails0_, emails0_.email_index as email3_0_ from email emails0_ where emails0_.Employee_id=?
Hibernate: insert into email (Employee_id, email_index, emails) values (?,?,?)
Employee 
  Id: 1
  Name: yogesh
  Emails: [[email protected], [email protected], [email protected], [email protected]]

Here, we can see that we have two e-mail addresses with the same value, [email protected]. This happens because here we used List, and it allows the existence of duplicate elements.

Deleting a record

Here, we will try to delete the record of Employee#1 from the database using the following code:

Code

  Employee employee = new Employee();
  employee.setId(1);
  session.getTransaction().begin();
  session.delete(employee);
  session.getTransaction().commit();

Output

Hibernate: delete from email where Employee_id=?
Hibernate: delete from employee where id=?

While deleting the employee record, hibernate also deletes all the child records associated with Employee#1; in our case, these are the e-mail addresses.

How it works…

When we use hbm2dll=auto|update, hibernate will create two tables for us: one is employee and the other is email:

How it works…

An important point that needs to be highlighted here is as follows:

  @ElementCollection(fetch=FetchType.LAZY)
  @CollectionTable(name = "email")
  @IndexColumn(name="email_index")
  private List<String> emails;

Let's take a look at the preceding code in detail:

  • @CollectionTable: This annotation indicates that the current field is of the Collection type, and hibernate creates a separate table for it. It also creates a reference between them. In this case, hibernate creates a table named email with email and employee_id. The employee_id column is made by joining the persisted class name and the primary key column of the employee class with an underscore (_).
  • @ElementCollection: This annotation is used to define the relationship with the embedded or basic type.

Here, we also use the fetch=FetchType.LAZY attribute, which means that hibernate will load a child or referenced record on demand only. In our Retrieving a record example, it will execute the employee and e-mail queries separately. Hibernate uses FetchType.LAZY if no attribute is defined for fetch.

Another possible value with the fetch attribute is FetchType.EAGER, which means that hibernate will load all the child records at the time of the retrieval of the parent record. In other words, it eagerly loads all the records. If we use FetchType.EAGER, hibernate uses the following query:

Hibernate:
SELECT 
  employee0_.id AS id0_0_,
  employee0_.name AS name0_0_,
  emails1_.Employee_id AS Employee1_0_2_,
  emails1_.emails AS emails2_,
  emails1_.email_index AS email3_2_ 
FROM
  employee employee0_ 
  LEFT OUTER JOIN email emails1_ 
    ON employee0_.id = emails1_.Employee_id 
WHERE employee0_.id = ?

The preceding code uses left outer join to get the child records, the reason being that when we use FetchType.LAZY, hibernate executes a separate query to load the child or referenced record.

If we use FetchType.EAGER, hibernate will use the JOIN query to get the child records.

Here, hibernate uses the left outer join to get child records, because FetchType.EAGER is used in the code.

@IndexColumn(name="email_index")

This annotation is used to hold the indexes of the collection's elements. This means that Hibernate creates a separate column in the child table (here, email) with the value given in the attribute name (here, email_index). This column preserves the sequence of the collection objects and helps while retrieving the records.

There's more…

In the preceding example, we dealt with List of the basic data type, which means that we used List of String (List<String>). Now, let's consider that we have a Degree class, which contains the degree name and passing year and want to map it with Employee. For this, we deal with List<Object> instead of List<String>. In our case, it will be List<Degree>. Let's take a look at how to do it.

Creating classes

Use the following code to create the classes:

Source file: Degree.java

@Entity
@Table(name="degree")
public class Degree {
  
  @Id
  @GeneratedValue
  private long id;
  
  @Column(name="degreename")
  private String degreeName;
  
  @Column(name="passingyear")
  private int passingYear;

  public Degree() {
  
  }
  
  public Degree(String degreeName, int passingYear) {
    this.degreeName = degreeName;
    this.passingYear = passingYear;
  }

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getDegreeName() {
    return degreeName;
  }

  public void setDegreeName(String degreeName) {
    this.degreeName = degreeName;
  }

  public int getPassingYear() {
    return passingYear;
  }

  public void setPassingYear(int passingYear) {
    this.passingYear = passingYear;
  }

  @Override
  public String toString() {
    return "

Degree " 
        + "
	Id:" + this.id
        + "
	Name:" + this.degreeName
        + "
	Passing year:" + this.passingYear;
  }
}

Source file: Employee.java

@Entity
@Table(name = "employee")
public class Employee {

  @Id
  @GeneratedValue
  @Column(name = "id")
  private long id;

  @Column(name = "name")
  private String name;

  @OneToMany(cascade={CascadeType.ALL})
  private List<Degree> degrees;

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List<Degree> getDegrees() {
    return degrees;
  }

  public void setDegrees(List<Degree> degrees) {
    this.degrees = degrees;
  }

  @Override
  public String toString() {
    return "Employee " 
        + "
	Id: " + this.id 
        + "
	Name: " + this.name
        + "
	Degrees: " + this.degrees;
  }
}

When we create SessionFactory with the hbm2dll=create|update option, hibernate will create the employee, degree and employee_degree tables for us; otherwise, you can use the following table script:

Creating classes

Creating tables

Use the following script to create tables if you are not using hbm2dll=create|update. This script is for the tables that are generated by hibernate.

Use the following code to create the degree table:

CREATE TABLE `degree` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`degreename` varchar(255) DEFAULT NULL,`passingyear` int(11) DEFAULT NULL,PRIMARY KEY (`id`));

Use the following code to create the employee table:

CREATE TABLE `employee` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`));

Use the following code to create the employee_degree table:

CREATE TABLE `employee_degree` (`employee_id` bigint(20) NOT NULL,`degrees_id` bigint(20) NOT NULL,UNIQUE KEY `degrees_id` (`degrees_id`),KEY `FK9CF457D5DB631AF` (`degrees_id`),KEY `FK9CF457D699100AA` (`employee_id`),CONSTRAINT `FK9CF457D699100AA` FOREIGN KEY (`employee_id`) REFERENCES `employee` (`id`),CONSTRAINT `FK9CF457D5DB631AF` FOREIGN KEY (`degrees_id`) REFERENCES `degree` (`id`));

Here, we used @OneToMany(cascade={CascadeType.ALL}) to map degree with employee.

Refer to the following code that shows how to insert/display records.

Inserting a record

Here, we insert one employee record with the two degrees associated with this employee.

Code

Use the following code to insert an employee record with degrees:

Employee employee = new Employee();
employee.setName("yogesh");

List<Degree> degrees = new ArrayList<Degree>();
degrees.add(new Degree("B.E.", 2008));
degrees.add(new Degree("M.S.", 2011));

employee.setDegrees(degrees);

session.getTransaction().begin();
session.save(employee);
session.getTransaction().commit();

Output

Hibernate: insert into employee (name) values (?)
Hibernate: insert into degree (degreename, passingyear) values (?, ?)
Hibernate: insert into degree (degreename, passingyear) values (?, ?)
Hibernate: insert into employee_degree (employee_id, degrees_id) values (?, ?)
Hibernate: insert into employee_degree (employee_id, degrees_id) values (?, ?)

Here, from the SQL statements, we understand that the first SQL statement inserts one record in to the employee table, the next two statements create two records in the degree table, and the last two statements create the mapping records in the employee_degree table using the inserted values of both the employee and degree tables.

Retrieving a record

Here, we will fetch the record of Employee#1 from the database. Use the following code to do so:

Code

Employee employee = (Employee) session.get(Employee.class, 1l);
System.out.println(employee.toString());

Output

Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from employee employee0_ where employee0_.id=?
Hibernate: select degrees0_.employee_id as employee1_0_1_, degrees0_.degrees_id as degrees2_1_, degree1_.id as id1_0_, degree1_.degreename as degreename1_0_, degree1_.passingyear as passingy3_1_0_ from employee_degree degrees0_ inner join degree degree1_ on degrees0_.degrees_id=degree1_.id where degrees0_.employee_id=?
Employee 
  Id: 1
  Name: yogesh
  Degrees: [

Degree 
  Id: 1
  Name: B.E.
  Passing year: 2008, 

Degree 
  Id: 2
  Name: M.S.
  Passing year: 2011]
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.44.53