Java Hibernate reference

1- Introduction

 This is a reference document on some issues related to Hibernate. You should preview the document below for easy reference:

2- Downloading the libraries which control some Databases

 When you work on some database, you need to have a library to control it.
  • Oracle
  • MySQL
  • SQLServer
  • HSQL
  • ....
See more:
We have the result:

3- Hibernate configuration on diferent databases.

3.1- Hibernate configuration for Oracle.

 First of all, you have to declare the library controlling the Oracle database (the above instruction).
 Hibernate configuration:
hibernate.cfg.xml (Oracle)
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
                     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                      "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>  
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:db11g</property>    
<property name="connection.username">simplehr</property>
<property name="connection.password">1234</property>


<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">2</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>


<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>


 <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
 <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

3.2- Hibernate congiguration for MySQL

 First of all, you have to declare the library controlling the  MySQL database  (the above instruction).
Hibernate configuration
hibernate.cfg.xml (MySQL)
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
 <!-- Database connection settings -->
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 <property name="connection.url">jdbc:mysql://tran-vmware:3306/simplehr</property>
 <property name="connection.username">root</property>
 <property name="connection.password">1234</property>

 <!-- JDBC connection pool (use the built-in) -->
 <property name="connection.pool_size">1</property>

 <!-- SQL dialect -->
 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

 <!-- Enable Hibernate's automatic session context management -->
 <property name="current_session_context_class">thread</property>

 <!-- Disable the second-level cache  -->
 <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

 <!-- Echo all executed SQL to stdout -->
 <property name="show_sql">true</property>

  <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
  <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

3.3- Hibernate congiguration for SQL Server

 First of all, you have to declare the SQLServer database driver library (the instructions above).
 
Hibernate configuration (Use JTDS library)
hibernate.cfg.xml (SQL Server)
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <!-- Database connection settings -->
  <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
  <property name="connection.url">jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS</property>
  <property name="connection.username">sa</property>
  <property name="connection.password">1234</property>

  <!-- JDBC connection pool (use the built-in) -->
  <property name="connection.pool_size">1</property>

  <!-- SQL dialect -->
  <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

  <!-- Enable Hibernate's automatic session context management -->
  <property name="current_session_context_class">thread</property>

  <!-- Disable the second-level cache  -->
  <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

  <!-- Echo all executed SQL to stdout -->
  <property name="show_sql">true</property>

   <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

</session-factory>
</hibernate-configuration>

4- Hibernate & Java Persistence Annotation

Hibernate uses Annotations to describe information for an Entity. It can use the annotations in the API of the hibernate located in the package org.hibernate.annotations or use the annotations in the package javax.persistence of the Java Persistence API. And in fact, the Annotations of the Java Persistence API is preferred.

In this section, I make a list of most common annotations of the Java Persistence API that are involved in the annotation for the  Entity.

4.1- @Entity

@Entity used to annotate a class is an Entity.
// Phần tử (element) name của @Entity là không bắt buộc.
// Việc chỉ định rõ name của @Entity cho phép viết ngắn câu HSQL

@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable {
    
}

// Phần tử (element) name của @Entity là không bắt buộc.
// Entity khớp với một bảng lấy theo tên theo thứ tự ưu tiên:
//  1 - name trong @Table
//  2 - name trong @Entity
//  3 - name của class.
// Việc chỉ định rõ name của @Entity cho phép viết ngắn câu HSQL

@Entity(name="AccTransaction")
@Table(name = "ACC_TRANSACTION")
public class AccTransaction implements Serializable {

}
 
 Indicating the name of @Entity helps you shorten the HSQL statement. Please look at the illustration:
// @Entity chú thích trên class Account không chỉ định rõ phần tử name.
// Vì vậy câu HSQL bắt buộc phải viết:

String hsql1 = "Select o from "+ Account.class.getName() +" o ";


// @Entity chú thích trên class AccTransaction
// chỉ định rõ phần tử name = "AccTransaction"
// Vì vậy câu HSQL có thể viết ngắn gọn:

String hsql2 = "Select o from AccTransaction o";

4.2- @Table

  A table in the DB can have many unique constraints. @Table also allow you to annotate it.
// @Table cho phép chú thích tên bảng
// Các giàng buộc duy nhất trong bảng.
// Phần tử name không bắt buộc.
// Nếu bạn không chỉ rõ tên bảng trong phần tử name ...
// .. Hibernate sẽ dựa vào phần tử name của @Entity sau đó mới
// tới tên của class.

@Table( name = "invoice_header",
           uniqueConstraints = @UniqueConstraint(columnNames ={ "invoice_num" }   )
)
@Entity
public class InvoiceHeader  implements java.io.Serializable {

       private String invoiceNum;


      @Column(name = "invoice_num", nullable = false, length = 20)
      public String getInvoiceNum() {
          return this.invoiceNum;
      }

}

4.3- @Id

For example, @Id participates in the  ID (Identity) annotation of the  Entity, which is equivalent to the understanding that this column is the primary key of the table.
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    private Integer empId;

    // @Id chú thích đây là id của Entity.
    // Và EMP_ID chính là khóa chính (Primary Key) của bảng.

    @Id
    @GeneratedValue
    @Column(name = "EMP_ID")
    public Integer getEmpId() {
        return empId;
    }

     ......
}

4.4- @GeneratedValue

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {

  // GenerationType: AUTO, TABLE, SEQUENCE, IDENTITY
  GenerationType strategy() default AUTO;

  String generator() default "";

}
@GeneratedValue is annotated for  Hibernate to automatically generate a value and mounts it into a column in case of inserting a new Entity into the database. It can be mounted on an ID column or some column.

Sometimes, it is also annotated with @Generator
 

4.4.1- GenerationType.AUTO

// Chú thích @GeneratedValue tương đương với
// @GeneratedValue(strategy=GenerationType.AUTO)

@GeneratedValue
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
    return empId;
}
The column annotated by @GeneratedValue (strategy = AUTO) will be assigned an auto-value, which can be generated by SEQUENCE or increase by itself (if this column is IDENTITY type). It depends on the DB type.
With Oracle, Postgres, hibernate it will call a Sequence named Hibernate_Sequence to create an incremental value to assign values to this column. With other DBs such as MySQL, DB2, SQL Server, Sysbase the column can be IDENTITY type and its value can increase  itself.

4.4.2- GenerationType.IDENTITY

The column is of IDENTITY type is supported by some Databases but all of them, for example,  MySQL, DB2, SQL Server, Sybase and  Postgres. Oracle doesn't support a column like this.
 
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
   return empId;
}

4.4.3- GenerationType.SEQUENCE

  SEQUENCE is an object in a database, storing an incremental value after each call to get the next value, and is supported by Oracle, DB2 and Postgres.
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
@Column(name = "EMP_ID")
public Integer getEmpId() {
   return empId;
}

4.4.4- GenerationType.TABLE

@Entity
public class Employee {
    ...
    @TableGenerator(
        name="empGen",
        table="ID_GEN_TABLE",
        pkColumnName="KEY_COLUMN",
        valueColumnName="VALUE_COLUMN",
        pkColumnValue="EMP_ID",
        allocationSize=1)
    @Id
    @GeneratedValue(strategy=TABLE, generator="empGen")
    public Long getEmpId()  {
       return empId;
    }
    ...
}


@Entity
public class Department {
    ...
    @TableGenerator(
        name="deptGen",
        table="ID_GEN_TABLE",
        pkColumnName="KEY_COLUMN",
        valueColumnName="VALUE_COLUMN",
        pkColumnValue="DEPT_ID",
        allocationSize=1)
    @Id
    @GeneratedValue(strategy=TABLE, generator="deptGen")
    public Long getDeptId()  {
       return deptId;
    }
    ...
}
 

 Note:  You can customize table name and column name (ID_GEN_TABLE, KEY_COLUMN, VALUE_COLUMN)

4.4.5- UUID

UUID is a class of Java that allows you to create a random 36-character string. And with 36 characters, identical probability is extremely small.

You can also annotate in order that the  Hibernate generates a random string of this type assigned to the value of the column.
 // Sử dụng strategy = "uuid2".

@GenericGenerator(name="my-uuid", strategy = "uuid2")
@GeneratedValue(generator="my-uuid")
@Id
@Column(name = "EMP_ID", length = 36)
public String getEmpId()  {
   return empId;
}

4.5- @Column

@Column annotates a column, including the information about column length , allowing null or not.
// Đây là một cột kiểu chuỗi, vì thế length luôn có ý nghĩa và cần thiết
// nullable mặc định là true
// length mặc định là 255

@Column(name = "FIRST_NAME", length = 20, nullable = false)
public String getFirstName() {
    return firstName;
}


// @Column không chỉ rõ phần tử length, mặc định nó là 255.

@Column(name = "DESCRIPTION", nullable = true )
public String getDescription() {
    return firstName;
}

// Với các cột kiểu số hoặc Date bạn có thể bỏ qua length
// (Nó không có ý nghĩa trong trường hợp này).

@Column(name = "PENDING_BALANCE")
public Float getPendingBalance() {
    return pendingBalance;
}




 

4.6- @Lob

@L ob are usually annotated with @Column to say that such column is of BLOB type  or CLOB type.
// Chú ý rằng trong một số Database có phân biệt TINY, MEDIUM, LARGE BLOB/CLOB.
// Còn một số database thì không.
// Phần tử length trong @Column trong trường hợp này sẽ quyết định nó map
// vào BLOB/CLOB nào.
// Trong trường hợp cho phép BLOB/CLOB tối đa hãy để length = Integer.MAX_VALUE


// Method này trả về byte[]
// @Lob trong trường hợp này chú thích cho cột BLOB

@Lob
@Column(name = "IMAGE_VALUE", nullable = true, length = Integer.MAX_VALUE)
public byte[] getImageValue() {
    this.imageValue;
}

// Method này trả về String
// @Lob trong trường hợp này sẽ chú thích cho CLOB.

@Lob
@Column(name = "ARTICLE_CONTENT", nullable = true, length = Integer.MAX_VALUE)
public String getArticleContent() {
    this.articleContent;
}

4.7- @Temporal

@Temporal  is used to annotate datetime column.
 
// @Temporal sử dụng chú thích cho cột có kiểu dữ liệu ngày tháng.
// Có 3 giá trị cho TemporalType:
// 1 - TemporalType.DATE
// 2 - TemporalType.TIME
// 3 - TemporalType.TIMESTAMP

@Temporal(TemporalType.DATE)
@Column(name = "START_DATE", nullable = false)
public java.util.Date getStartDate() {
    return startDate;
}

// TemporalType.DATE chú thích cột sẽ lưu trữ ngày tháng năm (bỏ đi thời gian)
// TemporalType.TIME chú thích cột sẽ lưu trữ thời gian (Giờ phút giây)
// TemporalType.TIMESTAMP chú thích cột sẽ lưu trữ ngày tháng và cả thời gian

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "FUNDS_AVAIL_DATE", nullable = false)
public java.util.Date getFundsAvailDate() {
      return fundsAvailDate;
}

4.8- @ManyToOne

@ManyToOne  describes one relationship  N-1 (Many -one), which is usually used with @JoinColumn.
 
@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable {

 
    private Branch openBranch;
 
   // Phần tử foreignKey giúp chỉ rõ tên Foreign Key trong DB.
   // Điều này sẽ giúp Hibernate tạo ra DB từ các Entity java một cách chính xác hơn.

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OPEN_BRANCH_ID", nullable = false,
                 foreignKey = @ForeignKey(name = "ACCOUNT_BRANCH_FK"))
    public Branch getOpenBranch() {
        return openBranch;
    }

}
Hibernate has the tools that allow you to generate  Entity classes from tables in the Database. And Hibernate also allows you to generate a table from Entity classes, including constraints between tables (Foreign Key). The @ForeignKey annotation allows indicating that the name  Foreign Key will be generated.
@ForeignKey is introduced in JPA from version 2.1
// Phần tử fetch có 2 giá trị
// 1 - FetchType.LAZY
// 2 - FetchType.EAGER

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "OPEN_BRANCH_ID", nullable = false,
             foreignKey = @ForeignKey(name = "ACCOUNT_BRANCH_FK"))
public Branch getOpenBranch() {
    return openBranch;
}

LAZY:

  LAZY tells Hibernate that, "please load data lazily".
For example, you have an Account and call the getOpenBranch() method, it returns a Branch,  in Branch object, only branchId field assigned a value, and  other fields are not.

In fact, hibernate has not loaded data from the corresponding record of the BRANCH table into this object. It only performs a data query when you do something with the Branch you have just acquired, such as calling the branch.getName() method.

 

EAGER:

  EAGER tells Hibernate to query all columns of the relevant table.
For example, you have an Account, and call the getOpenBranch() method, it returns the Branch of which values for the fields ( name, address, ...) are available. Actually, its data is acquired in a same query with the Account table.
You should use LAZY instead of EAGER for program performance reason.

4.9- @OneToMany

@OneToMany is the annotation to retrieve a list of subrecords of  current record (This is a many-one relationship). It is the reverse of @ManyToOne annotation, and therefore, it relies on @ManyToOne annotation to define @OneToMany.
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    ....

    private Department department;
 
    // Quan hệ N-1 (Nhiều - Một) định nghĩa department.   

    @JoinColumn(name = "DEPT_ID", nullable = true,
              foreignKey = @ForeignKey(name = "EMPLOYEE_DEPARTMENT_FK"))    
    @ManyToOne(fetch = FetchType.LAZY)    
    public Department getDepartment() {
        return department;
    }
 

}



@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable {

        .....

    private Set<Employee> employees = new HashSet<Employee>(0);

    // Quan hệ 1-N (Một - Nhiều) sử dụng mappedBy = "department"
    // đã định nghĩa ở quan hệ N-1 (phía trên).

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    public Set<Employee> getEmployees() {
        return employees;
    }
}

4.10- @OrderBy

@OrderBy is used to arrange a collection, therefore, it can be used with @OneToMany:

@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable {

        .....

    private Set<Employee> employees = new HashSet<Employee>(0);

    // Mặc định @OrderBy("empNo") tương đương với @OrderBy("empNo asc").
    // Nó tạo ra câu SQL: Select ... from Employee ... order by EMP_NO desc

    @OrderBy("empNo desc")
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    public Set<Employee> getEmployees() {
        return employees;
    }
}

4.11- @Transient

 Let's see a case:
@Entity
@Table(name="Employee")
public class Employee implements Serializable {
 
      .....

      @Column(name="FIRST_NAME", nullable =false , length = 20 )
      public String getFirstName()  {
           return this.firstName;
      }

      @Column(name="LAST_NAME", nullable =false , length = 20)
      public String getLastName()  {
           return this.lastName;
      }

     public String getFullName()  {
          return this.firstName+ " "+ this.lastName;
     }
}
You want to write a getFullName() method, which is only a calculation, not related to any column under the DB. Therefore, you need to use @Transient to notify your intent to  Hibernate.
@Transient
public String getFullName()  {
     return this.firstName+ " " + this.lastName;
}

@Transient
public boolean isManagerEmployee()  {
      return this.manager != null;
}

4.12- @Inheritance

View more categories: