betacode

Руководство Java Hibernate для начинающих

  1. Подготовить базу данных
  2. Создать Maven Project & Объявить библиотеку
  3. Классы Entity
  4. Конфигурация Hibernate
  5. SessionFactory
  6. Hibernate Query Language (HQL)
  7. Query данные с Hibernate
  8. Что такое Transient, Persistent и Detached?
  9. Цикл у Hibernate (Hibernate Lifecycle)
  10. Действия Insert, Update, Delete с Hibernate
  11. Tạo ra các bảng từ các lớp Entity

1. Подготовить базу данных

Hibernate является библиотекой, созданной для работы со всеми видами DB (баз данных), он не зависит от какого вида DB вы выбираете. Если Java это "Написать 1 раз, запустить везде", то Hibernate это "Написать 1 раз, запустить на всех видах DB"
В данной статье я использую simplehr, это простая база данных, использующаяся во многих статьях на o7planning. Вы можете создать ее с одной из базой данных как Oracle, MySQL или SQL Server. Смотрите инструкцию ниже:

2. Создать Maven Project & Объявить библиотеку

Здесь я создаю Maven project, и объявляю библиотеки Hibernate в pom.xml.
  • File/New/Other...
Project is created.
В pom.xml я объявляю библиотеку Hibernate 5, и библиотеки JDBC для разных видов базы данных Oracle, MySQL и SQL Server.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
               http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.o7planning</groupId>
    <artifactId>HibernateTutorial</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>HibernateTutorial</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>


    <repositories>
        <!-- Repository for ORACLE JDBC Driver -->
        <repository>
            <id>codelds</id>
            <url>https://code.lds.org/nexus/content/groups/main-repo</url>
        </repository>
    </repositories>
   
   
    <dependencies>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Hibernate Core -->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.2.Final</version>
        </dependency>


        <!-- MySQL JDBC driver -->
        <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>

        <!-- Oracle JDBC driver -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>

        <!-- SQLServer JDBC driver (JTDS) -->
        <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
        <dependency>
            <groupId>net.sourceforge.jtds</groupId>
            <artifactId>jtds</artifactId>
            <version>1.3.1</version>
        </dependency>

    </dependencies>
   
</project>

3. Классы Entity

Мы создаем класс Entity. Каждый Entity будет представлять таблицу в DB. Пока не будем затрагивать, что находится в тех классах.
  • Department - Департамент
  • Employee - Сотрудник
  • SalaryGrade - Уровень зарплаты
  • Timekeeper - Биометрические системы учета рабочего времени сотрудников.

Department.java
package org.o7planning.tutorial.hibernate.entities;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "DEPARTMENT",
  uniqueConstraints = { @UniqueConstraint(columnNames = { "DEPT_NO" }) })
public class Department {

private Integer deptId;
private String deptNo;

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

public Department() {
}

public Department(Integer deptId, String deptName, String location) {
   this.deptId = deptId;
   this.deptNo = "D" + this.deptId;
   this.deptName = deptName;
   this.location = location;
}

@Id
@Column(name = "DEPT_ID")
public Integer getDeptId() {
   return deptId;
}

public void setDeptId(Integer deptId) {
   this.deptId = deptId;
}

@Column(name = "DEPT_NO", length = 20, nullable = false)
public String getDeptNo() {
   return deptNo;
}

public void setDeptNo(String deptNo) {
   this.deptNo = deptNo;
}

@Column(name = "DEPT_NAME", nullable = false)
public String getDeptName() {
   return deptName;
}

public void setDeptName(String deptName) {
   this.deptName = deptName;
}

@Column(name = "LOCATION")
public String getLocation() {
   return location;
}

public void setLocation(String location) {
   this.location = location;
}

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

public void setEmployees(Set<Employee> employees) {
   this.employees = employees;
}
}
Employee.java
package org.o7planning.tutorial.hibernate.entities;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "EMPLOYEE",
   uniqueConstraints = { @UniqueConstraint(columnNames = { "EMP_NO" }) })
public class Employee {
private Long empId;
private String empNo;

private String empName;
private String job;
private Employee manager;
private Date hideDate;
private Float salary;
private byte[] image;

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

public Employee() {
}

public Employee(Long empId, String empName, String job, Employee manager,
        Date hideDate, Float salary, Float comm, Department department) {
    this.empId = empId;
    this.empNo = "E" + this.empId;
    this.empName = empName;
    this.job = job;
    this.manager = manager;
    this.hideDate = hideDate;
    this.salary = salary;
    this.department = department;
}

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

public void setEmpId(Long empId) {
    this.empId = empId;
}

@Column(name = "EMP_NO", length = 20, nullable = false)
public String getEmpNo() {
    return empNo;
}

public void setEmpNo(String empNo) {
    this.empNo = empNo;
}

@Column(name = "EMP_NAME", length = 50, nullable = false)
public String getEmpName() {
    return empName;
}

public void setEmpName(String empName) {
    this.empName = empName;
}

@Column(name = "JOB", length = 30, nullable = false)
public String getJob() {
    return job;
}

public void setJob(String job) {
    this.job = job;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MNG_ID")
public Employee getManager() {
    return manager;
}

public void setManager(Employee manager) {
    this.manager = manager;
}

@Column(name = "HIRE_DATE", nullable = false)
@Temporal(TemporalType.DATE)
public Date getHideDate() {
    return hideDate;
}

public void setHideDate(Date hideDate) {
    this.hideDate = hideDate;
}

@Column(name = "SALARY", nullable = false)
public Float getSalary() {
    return salary;
}

public void setSalary(Float salary) {
    this.salary = salary;
}

@Column(name = "IMAGE", length = 1111111, nullable = true)
@Lob
public byte[] getImage() {
    return image;
}

public void setImage(byte[] image) {
    this.image = image;
}

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

public void setDepartment(Department department) {
    this.department = department;
}

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

public void setEmployees(Set<Employee> employees) {
    this.employees = employees;
}

}
SalaryGrade.java
package org.o7planning.tutorial.hibernate.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "SALARY_GRADE")
public class SalaryGrade {
 private Integer grade;
 private Float lowSalary;
 private Float highSalary;

 public SalaryGrade() {
 }

 public SalaryGrade(Integer grade, Float lowSalary, Float highSalary) {
     this.grade = grade;
     this.lowSalary = lowSalary;
     this.highSalary = highSalary;
 }

 @Id
 @Column(name = "GRADE")
 public Integer getGrade() {
     return grade;
 }

 public void setGrade(Integer grade) {
     this.grade = grade;
 }

 @Column(name = "LOW_SALARY", nullable = false)
 public Float getLowSalary() {
     return lowSalary;
 }

 public void setLowSalary(Float lowSalary) {
     this.lowSalary = lowSalary;
 }

 @Column(name = "HIGH_SALARY", nullable = false)
 public Float getHighSalary() {
     return highSalary;
 }

 public void setHighSalary(Float highSalary) {
     this.highSalary = highSalary;
 }
}
Timekeeper.java
package org.o7planning.tutorial.hibernate.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "TIMEKEEPER")
public class Timekeeper {
  public static final char IN = 'I';
  public static final char OUT = 'O';

  private String timekeeperId;

  private Date dateTime;

  private Employee employee;

  // 'I' or 'O'
  private char inOut;

  @Id
  @GeneratedValue(generator = "uuid")
  @GenericGenerator(name = "uuid", strategy = "uuid2")
  @Column(name = "Timekeeper_Id", length = 36)
  public String getTimekeeperId() {
      return timekeeperId;
  }

  public void setTimekeeperId(String timekeeperId) {
      this.timekeeperId = timekeeperId;
  }

  @Column(name = "Date_Time", nullable = false)
  @Temporal(TemporalType.TIMESTAMP)
  public Date getDateTime() {
      return dateTime;
  }

  public void setDateTime(Date dateTime) {
      this.dateTime = dateTime;
  }

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "EMP_ID", nullable = false)
  public Employee getEmployee() {
      return employee;
  }

  public void setEmployee(Employee employee) {
      this.employee = employee;
  }

  @Column(name = "In_Out", nullable = false, length = 1)
  public char getInOut() {
      return inOut;
  }

  public void setInOut(char inOut) {
      this.inOut = inOut;
  }

}

4. Конфигурация Hibernate

Цель - это чтобы Hibernate смог прочитать Database, как и объявить список Entity, который вы создали в предыдущих шагах.
Файл hibernate.cfg.xml расположенный в src/main/java
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>

     <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
     <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
     <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:db11g</property>
     <property name="hibernate.connection.username">simplehr</property>
     <property name="hibernate.connection.password">12345</property>
     <property name="hibernate.show_sql">true</property>
     <property name="hibernate.connection.release_mode">auto</property>
     <property name="current_session_context_class">thread</property>
     <property name="hibernate.connection.autoReconnect">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>
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?serverTimezone=UTC</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>
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>
Для каждого Database имеется индивидуальный Dialect (Диалект).
Например:
Dialect для Oracle:
  • org.hibernate.dialect.Oracle10gDialect (Oracle 10g &11g)
  • org.hibernate.dialect.Oracle12cDialect
Dialect для SQL Server:
  • org.hibernate.dialect.SQLServerDialect
  • org.hibernate.dialect.SQLServer2012Dialect
  • org.hibernate.dialect.SQLServer2008Dialect
Dialect для MySQL:
  • org.hibernate.dialect.MySQLDialect
  • org.hibernate.dialect.MySQL5Dialect
Примечание: org.hibernate.dialect.Oracle10gDialect используется и для Oracle 10g, 11g, 12c.
Что такое Диалект?
Dialect это класс, который говорит Hibernate способ конвертирований видов данных у Database в виды данных Java, и наоборот. Одновременно, он используется для определения способа конвертирования между функциями HSQL (Hibernate SQL) в соответствующие функции Database.
Java SQL Type
Oracle
My SQL
SQL Server
Types.BIT
number(1,0)
bit
bit
Types.BIGINT
number(19,0)
bigint
bigint
Types.DATE
date
date
date
.......
Types.CLOB
clob
longtext
varchar(MAX)
Types.BLOB
blob
longblob
varbinary(MAX)

5. SessionFactory

HibernateUtils это утилитарный класс имеющий метод возвращающий объект SessionFactory. Данный класс постоянно используется в примерах.
HibernateUtils.java
package org.o7planning.tutorial.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtils {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    // Hibernate 5:
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the ServiceRegistry from hibernate.cfg.xml
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()//
                    .configure("hibernate.cfg.xml").build();

            // Create a metadata sources using the specified service registry.
            Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();

            return metadata.getSessionFactoryBuilder().build();
        } catch (Throwable ex) {
        
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }

}

6. Hibernate Query Language (HQL)

Hibernate использует язык Hibernate Query Language (HQL) для запроса данных. HQL имеет небольшое отличие по сравнению к SQL про которое вы не знали.
SQL:
  • Query (Запрос) данных на таблице.
HQL:
  • Query (Запрос) данных на классах Entity.
-- SQL
-- This is a SQL query in table DEPARTMENT.
Select d.DEPT_NO, d.DEPT_NAME from DEPARTMENT d;

-- HQL
-- This is a HQL query in Entity Department.
Select d.deptNo, d.deptName from Department d;

-- Query Object
Select d from Department d;
The rules of operation of Hibernate:
Ваше приложение пишет команды HQL, во время работы Hibernate сам знает с каким видом Database он работает, он автоматически конвертирует команды HQL в соответствующий SQL с тем видом DB4. На самом деле мы знаем синтаксис SQL имеет небольшие отличия между разными видами Database. Так же вид данных.
Вы можете просмотреть далее про синтаксис HQL по ссылке:


7. Query данные с Hibernate

Есть много способ запросить данные с Hibernate. В данной части я представлю несколько типичных способов запроса данных.
Query Object используя HQL
Первый пример, использование HQL для запроса объектов Entity:
QueryObjectDemo.java
package org.o7planning.tutorial.hibernate.query;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class QueryObjectDemo {

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();

       try {
           
           // All the action with DB via Hibernate
           // must be located in one transaction.
           // Start Transaction.            
           session.getTransaction().begin();

   
           
           // Create an HQL statement, query the object.
           // Equivalent to the SQL statement:
           // Select e.* from EMPLOYEE e order by e.EMP_NAME, e.EMP_NO
           String sql = "Select e from " + Employee.class.getName() + " e "
                   + " order by e.empName, e.empNo ";

  
           // Create Query object.
           Query<Employee> query = session.createQuery(sql);

   
           // Execute query.
           List<Employee> employees = query.getResultList();

           for (Employee emp : employees) {
               System.out.println("Emp: " + emp.getEmpNo() + " : "
                       + emp.getEmpName());
           }
 
           // Commit data.
           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           // Rollback in case of an error occurred.
           session.getTransaction().rollback();
       }
   }
   
}
Результат запуска примера:
Demo2:
QueryObjectDemo2.java
package org.o7planning.tutorial.hibernate.query;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class QueryObjectDemo2 {

    public static void main(String[] args) {
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        try {

            // All the action with DB via Hibernate
            // must be located in one transaction
            // Start Transaction.                
            session.getTransaction().begin();
            
            // Create an HQL statement, query the object.
            // HQL with parameters.            
            // Equivalent to the SQL statement:
            // Select e.* from EMPLOYEE e cross join DEPARTMENT d
            // where e.DEPT_ID = d.DEPT_ID and d.DEPT_NO = :deptNo;        
            String sql = "Select e from " + Employee.class.getName() + " e "
                    + " where e.department.deptNo=:deptNo ";
 
            // Create query object.
            Query<Employee> query = session.createQuery(sql);

            query.setParameter("deptNo", "D10");

 
            // Execute query.
            List<Employee> employees = query.getResultList();

            for (Employee emp : employees) {
                System.out.println("Emp: " + emp.getEmpNo() + " : "
                        + emp.getEmpName());
            }
 
            // Commit data
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            // Rollback in case of an error occurred.
            session.getTransaction().rollback();
        }
    }
}
Запросить данные нескольких столбцов используя HQL
QuerySomeColumnDemo.java
package org.o7planning.tutorial.hibernate.query;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class QuerySomeColumnDemo {

    public static void main(String[] args) {
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        try {
            session.getTransaction().begin();
 
            // Query some columns.
            String sql = "Select e.empId, e.empNo, e.empName from "
                    + Employee.class.getName() + " e ";

            Query<Object[]> query = session.createQuery(sql);
 
            // Execute Query.
            // Get the array of Object
            List<Object[]> datas = query.getResultList();

            for (Object[] emp : datas) {
                System.out.println("Emp Id: " + emp[0]);
                System.out.println(" Emp No: " + emp[1]);
                System.out.println(" Emp Name: " + emp[2]);
            }
 
            // Commit data.
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            // Rollback in case of an error occurred.
            session.getTransaction().rollback();
        }
 
    }
}
 
Результат запуска примера:
Запросить данные нескольких столбцов используя HQL & JavaBean
В случае вам нужно извлечь данные нескольких столбцов некоторых таблиц, лучший способ это использовать Java beans. Класс Java bean будет иметь constructor для создания значений его полей (field). Данный Constructor участвует в команде запроса HQL.
ShortEmpInfo.java
package org.o7planning.tutorial.hibernate.beans;

public class ShortEmpInfo {

    private Long empId;
    private String empNo;
    private String empName;

    //
    // Constructor have 3 parameters, will be used in the Hibernate Query.
    //
    public ShortEmpInfo(Long empId, String empNo, String empName) {
        this.empId = empId;
        this.empNo = empNo;
        this.empName = empName;
    }

    public Long getEmpId() {
        return empId;
    }

    public void setEmpId(Long empId) {
        this.empId = empId;
    }

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

}
ShortEmpInfoQueryDemo.java
package org.o7planning.tutorial.hibernate.query;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.beans.ShortEmpInfo;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class ShortEmpInfoQueryDemo {

    public static void main(String[] args) {
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        try {
            session.getTransaction().begin();
 
            // Using constructor of ShortEmpInfo
            String sql = "Select new " + ShortEmpInfo.class.getName()
                    + "(e.empId, e.empNo, e.empName)" + " from "
                    + Employee.class.getName() + " e ";

            Query<ShortEmpInfo> query = session.createQuery(sql);
 
            
            // Execute query.
            // Get a List of ShortEmpInfo
            List<ShortEmpInfo> employees = query.getResultList();

            for (ShortEmpInfo emp : employees) {
                System.out.println("Emp: " + emp.getEmpNo() + " : "
                        + emp.getEmpName());
            }
 
            // Commit data.
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            // Rollback in case of an error occurred.
            session.getTransaction().rollback();
        }
    }
    
}
Запрос единственного результата данных
UniqueResultDemo.java
package org.o7planning.tutorial.hibernate.query;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class UniqueResultDemo {

    public static Department getDepartment(Session session, String deptNo) {
        String sql = "Select d from " + Department.class.getName() + " d "//
                + " where d.deptNo= :deptNo ";
        Query<Department> query = session.createQuery(sql);
        query.setParameter("deptNo", deptNo);
        return (Department) query.getSingleResult();
    }

    public static Employee getEmployee(Session session, Long empId) {
        String sql = "Select e from " + Employee.class.getName() + " e "//
                + " where e.empId= :empId ";
        Query<Employee> query = session.createQuery(sql);
        query.setParameter("empId", empId);
        return (Employee) query.getSingleResult();
    }

    public static void main(String[] args) {
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        try {
            session.getTransaction().begin();

            Department dept = getDepartment(session, "D10");
            Set<Employee> emps = dept.getEmployees();

            System.out.println("Dept Name: " + dept.getDeptName());
            for (Employee emp : emps) {
                System.out.println(" Emp name: " + emp.getEmpName());
            }

            Employee emp = getEmployee(session, 7839L);
            System.out.println("Emp Name: " + emp.getEmpName());

            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
    }
    
}

8. Что такое Transient, Persistent и Detached?

DataUtils.java
package org.o7planning.tutorial.hibernate;

import org.hibernate.Session;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class DataUtils {

   public static Department findDepartment(Session session, String deptNo) {
       String sql = "Select d from " + Department.class.getName() + " d "//
               + " Where d.deptNo = :deptNo";
       Query<Department> query = session.createQuery(sql);
       query.setParameter("deptNo", deptNo);
       return query.getSingleResult();
   }

   public static Long getMaxEmpId(Session session) {
       String sql = "Select max(e.empId) from " + Employee.class.getName() + " e ";
       Query<Number> query = session.createQuery(sql);
       Number value = query.getSingleResult();
       if (value == null) {
           return 0L;
       }
       return value.longValue();
   }

   public static Employee findEmployee(Session session, String empNo) {
       String sql = "Select e from " + Employee.class.getName() + " e "//
               + " Where e.empNo = :empNo";
       Query<Employee> query = session.createQuery(sql);
       query.setParameter("empNo", empNo);
       return query.getSingleResult();
   }

}
Это простой пример использования Session.persist(Object), чтобы вставить объект Transient в DB. Понятие объекта Transitent, Persistent, Detached будет поясняться в данном примере.
PersistDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class PersistDemo {

   public static void main(String[] args) {
       
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Department department = null;
       Employee emp = null;
       try {
           session.getTransaction().begin();

           Long maxEmpId = DataUtils.getMaxEmpId(session);
           Long empId = maxEmpId + 1;
           
           // Get Persistent object.
           department = DataUtils.findDepartment(session, "D10");
           
           // Create transient object
           emp = new Employee();
           emp.setEmpId(empId);
           emp.setEmpNo("E" + empId);
           emp.setEmpName("Name " + empId);
           emp.setJob("Coder");
           emp.setSalary(1000f);
           emp.setManager(null);
           emp.setHideDate(new Date());
           emp.setDepartment(department);
           
           // Using persist(..)
           // Now 'emp' is managed by Hibernate.
           // it has Persistent status.
           // No action at this time with DB.
           session.persist(emp);

           
           // At this step the data is pushed to the DB.
           // Execute Insert statement.
           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }

       // After the session is closed (commit, rollback, close)
       // Objects 'emp', 'dept' became the Detached objects.
       // It is no longer in the control of the session.        
       System.out.println("Emp No: " + emp.getEmpNo());
       
   }
   
}
Результат запуска примера:

9. Цикл у Hibernate (Hibernate Lifecycle)

Класс Session у Hibernate имеет некоторые важные методы. Они разделены на группы как в изображении ниже.
Объект в Hibernate имеет 1 из 4-х статусов:
  • Transient (Временный)
  • Persistent (Постоянный)
  • Removed (Удален - ниже DB)
  • Detached (Отделен - по сравнению с настояющим session)
Мы объясняем эти статусы изображением ниже:
Transient:
В случае, когда вы создаете объект java из Entity, тот объект будет иметь статус Transient. Hibernate не знает про его существование. Он лежит вне управления Hibernate.
Persistent
В случае если вы извлекаете объект Entity через методы get, load, find, getSingleResult,.. вы получаете объект соответствующий с 1 записью внизу базы данных. Данный объект имеет статус Persistent. Он управляется с помощью Hibernate.
Transient -> Persistent
Session вызывает один из методов save, saveOrUpdate, persist, merge который толкает объект Transientв управлениеHibernate и данный объект меняет статус на Persistent. Он равен действию insert или update в Database.
Persistent -> Detached
Объект Session вызывает метод evict(..) или clear() чтобы выгнать объекты со статусом Persistent из управления Hibernate, теперь эти объекты будут иметь новый статус это Detached (Отделенный). Если он не будет перекреплен (Re-Attached), он будет удален с помощью Java (Java Garbage Collector) по обычному механизму.
Detached -> Persistent
Используя один из методов: update(..), saveOrUpdate(..), merge(..) дас объект со статусом Detached в управление Hibernate. Он соответствует действию update или insert внизу Database. Объект сменится на статус Persistent.
Persistent -> Removed
Объект Session вызывает метод remove(..) или delete(..) чтобы удалить объект (Запись), объект Persistent сменится на статус Removed (Удален).

10. Действия Insert, Update, Delete с Hibernate

Persistent
PersistentDemo.java
package org.o7planning.tutorial.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;

public class PersistentDemo {

   public static void main(String[] args) {
       
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Department department = null;

       try {
           session.getTransaction().begin();

           System.out.println("- Finding Department deptNo = D10...");
      
           // Persistent object.
           department = DataUtils.findDepartment(session, "D10");

           System.out.println("- First change Location");
     
           
           // Changing something on Persistent object.
           department.setLocation("Chicago " + System.currentTimeMillis());
           
           System.out.println("- Location = " + department.getLocation());

           System.out.println("- Calling flush...");
   
           // Use session.flush () to actively push the changes to the DB.
           // It works for all changed Persistent objects.
           session.flush();

           System.out.println("- Flush OK");

           System.out.println("- Second change Location");
           
           // Change something on Persistent object
           department.setLocation("Chicago " + System.currentTimeMillis());
 
           // Print out location
           System.out.println("- Location = " + department.getLocation());

           System.out.println("- Calling commit...");
 
           // Commit
           session.getTransaction().commit();

           System.out.println("- Commit OK");
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
 
       // Create the session after it had been closed earlier
       // (Cause by commit or update)
       session = factory.getCurrentSession();
       try {
           session.getTransaction().begin();

           System.out.println("- Finding Department deptNo = D10...");
           
           // Query lại Department D10.
           
           department = DataUtils.findDepartment(session, "D10");
 
           // Print out location
           System.out.println("- D10 Location = " + department.getLocation());

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
   
}
Результаты запуска примера:
Transient --> Persistent : Обзор
Transient --> Persistent : Используя persist(Object)
PersistTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;

public class PersistTransientDemo {

   private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

   private static Timekeeper persist_Transient(Session session, Employee emp) {
 
       // Note:
       // Configuring of timekeeperId
       // @GeneratedValue(generator = "uuid")
       // @GenericGenerator(name = "uuid", strategy = "uuid2")            
       Timekeeper tk1 = new Timekeeper();

       tk1.setEmployee(emp);
       tk1.setInOut(Timekeeper.IN);
       tk1.setDateTime(new Date());
  
       // Now, 'tk1' is transient object
       System.out.println("- tk1 Persistent? " + session.contains(tk1));

       System.out.println("====== CALL persist(tk).... ===========");
 
       
       // Hibernate assign value to Id of 'tk1'
       // No action to DB.
       session.persist(tk1);
 
       System.out
               .println("- tk1.getTimekeeperId() = " + tk1.getTimekeeperId());
 
       
       // Now 'tk1' is Persistent object.
       // But no action with DB.
       // ==> true
       System.out.println("- tk1 Persistent? " + session.contains(tk1));

       System.out.println("- Call flush..");
 
       
       // Flush data to DB.
       // Hibernate execute insert statement.
       session.flush();

       String timekeeperId = tk1.getTimekeeperId();
       System.out.println("- timekeeperId = " + timekeeperId);
       System.out.println("- inOut = " + tk1.getInOut());
       System.out.println("- dateTime = " + df.format(tk1.getDateTime()));
       System.out.println();
       return tk1;
   }

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       try {
           session.getTransaction().begin();

           emp = DataUtils.findEmployee(session, "E7499");

           persist_Transient(session, emp);

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
   
}
Результаты запуска примера:
Transient --> Persistent : Используя save(Object) *
SaveTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;

public class SaveTransientDemo {

   private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

   private static Timekeeper persist_Transient(Session session, Employee emp) {
     
       // See configuration of timekeeperId:
       // @GeneratedValue(generator = "uuid")
       // @GenericGenerator(name = "uuid", strategy = "uuid2")
       // Create an Object, Transitent state.        
       Timekeeper tk2 = new Timekeeper();

       tk2.setEmployee(emp);
       tk2.setInOut(Timekeeper.IN);
       tk2.setDateTime(new Date());

       // Now 'tk3' are state Transient.        
       System.out.println("- tk2 Persistent? " + session.contains(tk2));

       System.out.println("====== CALL save(tk).... ===========");

       // save() very similar to persist()
       // save() return ID, persist() return void.
       // Hibernate assign ID value to 'tk2', no action with DB
       // And return ID of 'tk2'.        
       Serializable id = session.save(tk2);

       System.out.println("- id = " + id);

       //
       System.out
               .println("- tk2.getTimekeeperId() = " + tk2.getTimekeeperId());

     
       // Now, 'tk2' has Persistent state
       // It has been managed in Session.
       // ==> true
       System.out.println("- tk2 Persistent? " + session.contains(tk2));

       System.out.println("- Call flush..");

       // To push data into the DB, call flush().
       // If not call flush() data will be pushed to the DB when calling commit().
       // Will execute insert statement.
       session.flush();

       String timekeeperId = tk2.getTimekeeperId();
       System.out.println("- timekeeperId = " + timekeeperId);
       System.out.println("- inOut = " + tk2.getInOut());
       System.out.println("- dateTime = " + df.format(tk2.getDateTime()));
       System.out.println();
       return tk2;
   }

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       try {
           session.getTransaction().begin();

           emp = DataUtils.findEmployee(session, "E7499");

           persist_Transient(session, emp);

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
}
Результаты запуска примера:
Transient --> Persistent : Используя saveOrUpdate(Object)
SaveOrUpdateTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;

public class SaveOrUpdateTransientDemo {

   private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

   private static Timekeeper saveOrUpdate_Transient(Session session,
           Employee emp) {

       // See configuration of timekeeperId:
       // @GeneratedValue(generator = "uuid")
       // @GenericGenerator(name = "uuid", strategy = "uuid2")
       // Create an Object, Transitent state.
       Timekeeper tk3 = new Timekeeper();

       tk3.setEmployee(emp);
       tk3.setInOut(Timekeeper.IN);
       tk3.setDateTime(new Date());

       // Now 'tk3' are state Transient.
       System.out.println("- tk3 Persistent? " + session.contains(tk3));

       System.out.println("====== CALL saveOrUpdate(tk).... ===========");

       // Here Hibernate checks, 'tk3' have ID or not (timekeeperId)
       // If no, it will be assigned automatically
       session.saveOrUpdate(tk3);

       System.out
               .println("- tk3.getTimekeeperId() = " + tk3.getTimekeeperId());

       // Now 'tk3' has Persistent state
       // It has been managed in Session.
       // But no action insert, or update to DB.
       // ==> true
       System.out.println("- tk3 Persistent? " + session.contains(tk3));

       System.out.println("- Call flush..");

       // To push data into the DB, call flush().
       // If not call flush() data will be pushed to the DB when calling commit().
       // Now possible to Insert or Update DB. (!!!)
       // Depending on the ID of 'tk3' exists in the DB or not
       session.flush();

       String timekeeperId = tk3.getTimekeeperId();
       System.out.println("- timekeeperId = " + timekeeperId);
       System.out.println("- inOut = " + tk3.getInOut());
       System.out.println("- dateTime = " + df.format(tk3.getDateTime()));
       System.out.println();
       return tk3;
   }

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       try {
           session.getTransaction().begin();

           emp = DataUtils.findEmployee(session, "E7499");

           saveOrUpdate_Transient(session, emp);

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
}
Результаты запуска примера:
Transient --> Persistent : Используя merge(Object)
MergeTransientDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;
import org.o7planning.tutorial.hibernate.entities.Timekeeper;

public class MergeTransientDemo {

   private static DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

   private static Timekeeper saveOrUpdate_Transient(Session session,
           Employee emp) {
     
       // Note:
       // Configuring of timekeeperId
       // @GeneratedValue(generator = "uuid")
       // @GenericGenerator(name = "uuid", strategy = "uuid2")        
       Timekeeper tk4 = new Timekeeper();

       tk4.setEmployee(emp);
       tk4.setInOut(Timekeeper.IN);
       tk4.setDateTime(new Date());

       // Now 'tk4' Transient status.
       System.out.println("- tk4 Persistent? " + session.contains(tk4));

       System.out.println("====== CALL merge(tk).... ===========");

 
       // Hibernate2 has method saveOrUpdateCopy
       // Hibernate3 change saveOrUpdateCopy to merge
       // So there will be similarities between the two methods merge and copyOrUpdate
       // Here Hibernate check tk4 has ID or not
       // If not, Hibernate assign value to ID of tk4
       // Return copy of tk4.
       Timekeeper tk4Copy = (Timekeeper) session.merge(tk4);

       System.out
               .println("- tk4.getTimekeeperId() = " + tk4.getTimekeeperId());

   
       // Now 'tk4' still Transient state.
       // and 'tk4Copy' has Persistent status
       // No action with DB (insert or update).
       System.out.println("- tk4 Persistent? " + session.contains(tk4));

       // 'tk4Copy' has Persistent status
       // ==> true
       System.out
               .println("- tk4Copy Persistent? " + session.contains(tk4Copy));

       System.out.println("- Call flush..");
       
     
       // This time have Insert or Update to DB. (!!!)
       session.flush();

       // 'tk4' still Transitent, after flush().
       // merge(..) safer than saveOrUpdate().
       System.out.println("- tk4 Persistent? " + session.contains(tk4));

       //
       String timekeeperId = tk4.getTimekeeperId();
       System.out.println("- timekeeperId = " + timekeeperId);
       System.out.println("- inOut = " + tk4.getInOut());
       System.out.println("- dateTime = " + df.format(tk4.getDateTime()));
       System.out.println();
       return tk4;
   }

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       try {
           session.getTransaction().begin();

           emp = DataUtils.findEmployee(session, "E7499");

           saveOrUpdate_Transient(session, emp);

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
}
Результаты запуска примера:
Persistent --> Detached
Объект имеет статус Persistent (Управляется с помощью Hibernate) может смениться на статус Detached (Отделенный, не управляется с помощью Hibernate) через методы ниже у Session:
  • evict(Object)
Выгнать объект из управления Hibernate
  • clear()
Выгнать все объекты из управления Hibernate.
Примечание: Когда объект Session вызывает один из методов: commit(), close(), rollback() тогда данный session (время работы) завершится. Все объекты Persistence данного session будут считаться Detached для нового session.
EvictDemo.java
package org.o7planning.tutorial.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class EvictDemo {

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       try {
           session.getTransaction().begin();

           // This is object has Persistent status
           emp = DataUtils.findEmployee(session, "E7499");

           // ==> true
           System.out.println("- emp Persistent? " + session.contains(emp));

     
           // using evict() to evicts a single object from the session
           session.evict(emp);

           // Now 'emp' has Detached status
           // ==> false
           System.out.println("- emp Persistent? " + session.contains(emp));

       
           // All change on the 'emp' will not update
           // if not reatach 'emp' to session
           emp.setEmpNo("NEW");

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
}
Results of running the example:
ClearDemo.java
package org.o7planning.tutorial.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Department;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class ClearDemo {
   
   
   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session = factory.getCurrentSession();
       Employee emp = null;
       Department dept = null;
       try {
           session.getTransaction().begin();

           // It is an object has Persistent status.
           emp = DataUtils.findEmployee(session, "E7499");
           dept = DataUtils.findDepartment(session, "D10");

       
           // clear() evicts all the objects in the session.
           session.clear();


           // Now 'emp' & 'dept' has Detached status
           // ==> false
           System.out.println("- emp Persistent? " + session.contains(emp));
           System.out.println("- dept Persistent? " + session.contains(dept));

           // All change on the 'emp' will not update
           // if not reatach 'emp' to session
           emp.setEmpNo("NEW");

           dept = DataUtils.findDepartment(session, "D20");
           System.out.println("Dept Name = "+ dept.getDeptName());

           session.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session.getTransaction().rollback();
       }
   }
}
Результаты запуска примера:
Detached --> Persistent : Обзор
Объект имеет статус Detached (Отделен от управления Hibernate) может быть перекреплен (Re-attach) через некоторые методы у Session:
  • update(Object)
  • saveOrUpdate(Object)
  • merge(Object)
  • refresh(Object)
  • lock(Object)
Вы можете просмотреть отличие данных методов в следующих примерах:
Detached --> Persistent : Используя update(Object)
UpdateDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class UpdateDetachedDemo {

   public static void main(String[] args) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session1 = factory.getCurrentSession();
       Employee emp = null;
       try {
           session1.getTransaction().begin();

           // This is a Persistent object.
           emp = DataUtils.findEmployee(session1, "E7499");

           // session1 was closed after a commit is called.
           session1.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session1.getTransaction().rollback();
       }

       // Open other session
       Session session2 = factory.getCurrentSession();

       try {
           session2.getTransaction().begin();

       
           // Check state of 'emp'
           // ==> false
           System.out.println("- emp Persistent? " + session2.contains(emp));

           System.out.println("Emp salary: " + emp.getSalary());

           emp.setSalary(emp.getSalary() + 100);

         
           // update (..) is only used for Detached object.
           // (Not for Transient object).
           // Use the update (emp) to bring back emp Persistent state.            
           session2.update(emp);
         
           // Call flush
           // Update statement will be called.
           session2.flush();

           System.out.println("Emp salary after update: " + emp.getSalary());

           // session2 was closed after a commit is called.
           session2.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session2.getTransaction().rollback();
       }

   }
}
Результаты запуска примера:
Detached --> Persistent : Используя saveOrUpdate(Object)
SaveOrUpdateDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.util.Random;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class SaveOrUpdateDetachedDemo {

   public static void main(String[] args) {

       // An object Detached state.
       Employee emp = getEmployee_Detached();

       System.out.println(" - GET EMP " + emp.getEmpId());

       // Random delete or not delete Employee
       boolean delete = deleteOrNotDelete(emp.getEmpId());

       System.out.println(" - DELETE? " + delete);

       // Call saveOrUpdate for detached object.
       saveOrUpdate_test(emp);
     
       // After call saveOrUpdate()
       System.out.println(" - EMP ID " + emp.getEmpId());
   }

   
   // Return Employee object has Detached state
   private static Employee getEmployee_Detached() {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session1 = factory.getCurrentSession();
       Employee emp = null;
       try {
           session1.getTransaction().begin();

           Long maxEmpId = DataUtils.getMaxEmpId(session1);
           System.out.println(" - Max Emp ID " + maxEmpId);

           Employee emp2 = DataUtils.findEmployee(session1, "E7839");

           Long empId = maxEmpId + 1;
           emp = new Employee();
           emp.setEmpId(empId);
           emp.setEmpNo("E" + empId);

           emp.setDepartment(emp2.getDepartment());
           emp.setEmpName(emp2.getEmpName());

           emp.setHideDate(emp2.getHideDate());
           emp.setJob("Test");
           emp.setSalary(1000F);

           // emp has been managed by Hibernate
           session1.persist(emp);

           // session1 was closed after a commit is called.
           // An Employee record are insert into DB.            
           session1.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session1.getTransaction().rollback();
       }
       // Session1 closed 'emp' switch to Detached state.
       return emp;
   }

   // Random: delete or not delete.
   private static boolean deleteOrNotDelete(Long empId) {
       // A random number 0-9
       int random = new Random().nextInt(10);
       if (random < 5) {
           return false;
       }
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session2 = factory.getCurrentSession();
       try {
           session2.getTransaction().begin();
           String sql = "Delete " + Employee.class.getName() + " e "
                   + " where e.empId =:empId ";
           Query query = session2.createQuery(sql);
           query.setParameter("empId", empId);

           query.executeUpdate();

           session2.getTransaction().commit();
           return true;
       } catch (Exception e) {
           e.printStackTrace();
           session2.getTransaction().rollback();
           return false;
       }
   }

   private static void saveOrUpdate_test(Employee emp) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       // Open other session
       Session session3 = factory.getCurrentSession();

       try {
           session3.getTransaction().begin();

           // Check state of emp
           // ==> false
           System.out.println(" - emp Persistent? " + session3.contains(emp));

           System.out.println(" - Emp salary before update: "
                   + emp.getSalary());
         
           // Set new salary for Detached emp object.
           emp.setSalary(emp.getSalary() + 100);

         
           // Using saveOrUpdate(emp) to switch emp to Persistent state
           // Note: If exists object same ID in session, this method raise Exception
           //
           // Now, no action with DB.            
           session3.saveOrUpdate(emp);
         
           // By pushing data into the DB.
           // It will call a Insert or update statement.
           // If the record is deleted before ==> insert
           // Else ==> update.    
           session3.flush();

           System.out
                   .println(" - Emp salary after update: " + emp.getSalary());

           // session3 was closed after a commit is called.
           session3.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session3.getTransaction().rollback();
       }

   }

}
Запустить пример выше несколько раз, вы сможете увидеть 2 ситуации saveOrUpdateсоздает действия: Insert или Update в DB.
INSERT:
UPDATE:
Detached --> Persistent : Используя merge(Object)
Hibernate версия 2 имеет метод saveOrUpdateCopy(Object), с 3-й версии и далее он меняет название на merge(Object). Поэтому mergeимеет некоторые схожести и отличия по сравнению с saveOrUpdate.
merge(Object) не ставит объект под управление Hibernate, но создает копию объекта и управляем копией объекта.
Если вы вызываете saveOrUpdate(aObject) когда уже есть объект bObject управляемый с помощью Hibernate с одинаковым ID с aObject выбрасывается исключение. При этом, используя merge(aObject) данное исключение не будет выбрасываться.
MergeDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;

import java.util.Random;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class MergeDetachedDemo {

   public static void main(String[] args) {

       // An object has Detached status
       Employee emp = getEmployee_Detached();

       System.out.println(" - GET EMP " + emp.getEmpId());

       // Random: delete or not delete the Employee by ID.
       boolean delete = deleteOrNotDelete(emp.getEmpId());

       System.out.println(" - DELETE? " + delete);

       // Call saveOrUpdate Detached object
       saveOrUpdate_test(emp);

       // After call saveOrUpdate
       // ...
       System.out.println(" - EMP ID " + emp.getEmpId());
   }

 
   // Method return Employee object
   // and has Detached status.
   private static Employee getEmployee_Detached() {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session1 = factory.getCurrentSession();
       Employee emp = null;
       try {
           session1.getTransaction().begin();

           Long maxEmpId = DataUtils.getMaxEmpId(session1);
           System.out.println(" - Max Emp ID " + maxEmpId);

           Employee emp2 = DataUtils.findEmployee(session1, "E7839");

           Long empId = maxEmpId + 1;
           emp = new Employee();
           emp.setEmpId(empId);
           emp.setEmpNo("E" + empId);

           emp.setDepartment(emp2.getDepartment());
           emp.setEmpName(emp2.getEmpName());

           emp.setHideDate(emp2.getHideDate());
           emp.setJob("Test");
           emp.setSalary(1000F);

           // 'emp' has Persistant state
           session1.persist(emp);

       
           // session1 was closed after a commit is called.
           // An Employee record are insert into DB.
           session1.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session1.getTransaction().rollback();
       }
       // session1 closed, 'emp' switched Detached state.
       return emp;
   }

 
   // Delete Employee by ID
   // Random: delete or not delete
   private static boolean deleteOrNotDelete(Long empId) {
       // A random number 0-9
       int random = new Random().nextInt(10);
       if (random < 5) {
           return false;
       }
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session2 = factory.getCurrentSession();
       try {
           session2.getTransaction().begin();
           String sql = "Delete " + Employee.class.getName() + " e "
                   + " where e.empId =:empId ";
           Query query = session2.createQuery(sql);
           query.setParameter("empId", empId);

           query.executeUpdate();

           session2.getTransaction().commit();
           return true;
       } catch (Exception e) {
           e.printStackTrace();
           session2.getTransaction().rollback();
           return false;
       }
   }

   private static void saveOrUpdate_test(Employee emp) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       // Open other session
       Session session3 = factory.getCurrentSession();

       try {
           session3.getTransaction().begin();

       
           // The fact, 'emp' has Detached state
           // It is not managed by Hibernate.
           // Check the status of emp:
           // ==> false
           System.out.println(" - emp Persistent? " + session3.contains(emp));

           System.out.println(" - Emp salary before update: "
                   + emp.getSalary());

           // Set new salary for Detached object 'emp'
           emp.setSalary(emp.getSalary() + 100);

       
           // merge(emp) return empMerge, a copy of 'emp',
           // empMerge managed by Hibernate
           // 'emp' still in Detached state
           //
           // At this time there is no action regarding DB.
           Employee empMerge = (Employee) session3.merge(emp);

           // ==> false
           System.out.println(" - emp Persistent? " + session3.contains(emp));
           // ==> true
           System.out.println(" - empMerge Persistent? "
                   + session3.contains(empMerge));

         
           // Push data into the DB.
           // Here it is possible to create the Insert or Update on DB.
           // If the corresponding record has been deleted by someone, it insert
           // else it update
           session3.flush();

           System.out
                   .println(" - Emp salary after update: " + emp.getSalary());

           // session3 closed after a commit is called.
           session3.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session3.getTransaction().rollback();
       }

   }

}
Результат запуска примера:
INSERT:
UPDATE:
Detached --> Persistent : Используя refresh(Object)
RefreshDetachedDemo.java
package org.o7planning.tutorial.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.o7planning.tutorial.hibernate.DataUtils;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class RefreshDetachedDemo {

   public static void main(String[] args) {

       // an Object with Detached status
       Employee emp = getEmployee_Detached();

       System.out.println(" - GET EMP " + emp.getEmpId());

       // Refresh Object  
       refresh_test(emp);
   }

 
   // Return Employee object has Detached state
   private static Employee getEmployee_Detached() {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       Session session1 = factory.getCurrentSession();
       Employee emp = null;
       try {
           session1.getTransaction().begin();

           emp = DataUtils.findEmployee(session1, "E7839");

           // session1 was closed after a commit is called.
           // An Employee record are insert into DB.
           session1.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session1.getTransaction().rollback();
       }
       // Session1 closed 'emp' switch to Detached state.
       return emp;
   }

   private static void refresh_test(Employee emp) {
       SessionFactory factory = HibernateUtils.getSessionFactory();

       // Open other session
       Session session2 = factory.getCurrentSession();

       try {
           session2.getTransaction().begin();

       
           // Check the status of 'emp' (Detached)
           // ==> false
           System.out.println(" - emp Persistent? " + session2.contains(emp));

           System.out.println(" - Emp salary before update: "
                   + emp.getSalary());

            // Set new salary for 'emp'.
           emp.setSalary(emp.getSalary() + 100);

         
           // refresh: make a query statement
           // and switch 'emp' to Persistent state
           // The changes are ignored
           session2.refresh(emp);

           // ==> true
           System.out.println(" - emp Persistent? " + session2.contains(emp));

           System.out.println(" - Emp salary after refresh: "
                   + emp.getSalary());
           
           session2.getTransaction().commit();
       } catch (Exception e) {
           e.printStackTrace();
           session2.getTransaction().rollback();
       }

   }

}
Результаты запуска примера:
Detached --> Persistent : Using lock(Object)
  • TODO...

11. Tạo ra các bảng từ các lớp Entity

Hibernate позволяет вам создавать таблицы из классов Entity, с полными связями между таблицами.
No ADS