Hibernate快速入門

Hibernate是一個開源反砌,輕量級的ORM(對象關(guān)系映射)工具呻拌。Hibernate框架簡化了java應(yīng)用程序與數(shù)據(jù)庫交互的開發(fā)。

ORM工具簡化了數(shù)據(jù)創(chuàng)建媚值,數(shù)據(jù)處理和數(shù)據(jù)訪問狠毯。它是將對象映射到數(shù)據(jù)庫中存儲的數(shù)據(jù)(表)的編程技術(shù)。

注:為什么會有這篇教程文章褥芒?答:只是想寫一篇最NB的Hibernate教程入門文章嚼松。NB代表人見人愛,花見花開锰扶,車見爆胎,飛鳥落地...献酗,最后,需要注意的是:這篇文章包教不包會坷牛!除非你從頭到尾認真看完并運行所有示例代碼罕偎。

1. Hibernate快速入門簡介

本教程文章基于以下工具(軟件):

  • Hibernate 5.2.2.Final
  • Eclipse 4.6 (MARS)

Hibernate.x ~ Hibernate.5 更新功能:

  1. Hibernate 5.0開始Hibernate Spatial是Hibernate項目的一部分,因此我們也可以處理GIS數(shù)據(jù)了京闰。

  2. 域模型映射支持Java 8日期和時間類型颜及。 標(biāo)準SQL日期/時間類型以及支持的Java 8 Date / Time類類型之間的映射,如下所示:

  • DATE: java.time.LocalDate
  • TIME: java.time.LocalTime, java.time.OffsetTime
  • TIMESTAMP: java.time.Instant, java.time.LocalDateTime,java.time.OffsetDateTimejava.time.ZonedDateTime
  1. 字節(jié)碼增強機制從頭重新設(shè)計蹂楣,Hibernate可支持Maven和Gradle插件俏站。可以通過字節(jié)碼儀器來增強三個主要方面:
  • 懶初始化:字段可以聲明為LAZY痊土,只有在第一次被訪問時肄扎,它們才被提取。
  • 臟檢查:實體被增強施戴,使得它們可以跟蹤在持久化上下文中加載之后變化的所有屬性反浓。
  • 雙向關(guān)聯(lián):即使開發(fā)人員僅更新單側(cè),但也可以自動同步雙向關(guān)聯(lián)的雙方赞哗。
  1. Hibernate的原生API(Session等)已更新為使用泛型類型化雷则。無需在獲取實體時轉(zhuǎn)換。
  2. Hibernate 5.0將其擴展到更廣泛的類型(例如UUID)肪笋。
  3. 引用二級緩存月劈,使實體引用能夠直接存儲到第二級緩存中(用于不可變實體)度迂。

2. 準備數(shù)據(jù)庫

Hibernate是一個庫,為了處理所有類型的數(shù)據(jù)庫猜揪,它不依賴于應(yīng)用程序選擇的任何類型的數(shù)據(jù)庫惭墓,如果Java是“一次寫入到處運行”的語言,Hibernate則是“寫一次就可運行在所有類型的數(shù)據(jù)庫“中的框架而姐。

在這篇文章中腊凶,使用的是MySQL數(shù)據(jù)(你可使用其它的數(shù)據(jù)庫,如:Oracle拴念,MySQL或SQL Server)钧萍,并創(chuàng)建一個簡單的數(shù)據(jù)庫:mydb,完整的數(shù)據(jù)庫創(chuàng)建語句如下所示:

創(chuàng)建數(shù)據(jù):

CREATE DATABASE IF NOT EXISTS mydb default charset utf8 COLLATE utf8_general_ci; 

需要創(chuàng)建以下幾張表政鼠,它們的關(guān)系圖如下所示 -

創(chuàng)建表語句:

create table DEPARTMENT (
   DEPT_ID integer not null,
   DEPT_NAME varchar(255) not null,
   DEPT_NO varchar(20) not null,
   LOCATION varchar(255),
   primary key (DEPT_ID),
   unique (DEPT_NO)
);
 
create table EMPLOYEE (
   EMP_ID bigint not null,
   EMP_NAME varchar(50) not null,
   EMP_NO varchar(20) not null,
   HIRE_DATE date not null,
   IMAGE longblob,
   JOB varchar(30) not null,
   SALARY float not null,
   DEPT_ID integer not null,
   MNG_ID bigint,
   primary key (EMP_ID),
   unique (EMP_NO)
);
 
create table SALARY_GRADE (
   GRADE integer not null,
   HIGH_SALARY float not null,
   LOW_SALARY float not null,
   primary key (GRADE)
);
 
create table TIMEKEEPER (
   Timekeeper_Id varchar(36) not null,
   Date_Time datetime not null,
   In_Out char(1) not null,
   EMP_ID bigint not null,
   primary key (Timekeeper_Id)
);
 
alter table EMPLOYEE
   add index FK75C8D6AE269A3C9 (DEPT_ID),
   add constraint FK75C8D6AE269A3C9
   foreign key (DEPT_ID)
   references DEPARTMENT (DEPT_ID);
 
alter table EMPLOYEE
   add index FK75C8D6AE6106A42 (EMP_ID),
   add constraint FK75C8D6AE6106A42
   foreign key (EMP_ID)
   references EMPLOYEE (EMP_ID);
 
alter table EMPLOYEE
   add index FK75C8D6AE13C12F64 (MNG_ID),
   add constraint FK75C8D6AE13C12F64
   foreign key (MNG_ID)
   references EMPLOYEE (EMP_ID);
 
alter table TIMEKEEPER
   add index FK744D9BFF6106A42 (EMP_ID),
   add constraint FK744D9BFF6106A42
   foreign key (EMP_ID)
   references EMPLOYEE (EMP_ID);

向上面創(chuàng)建的表中风瘦,分別插入一些測試數(shù)據(jù),如下所示 -

insert into Department (DEPT_ID, DEPT_NAME, DEPT_NO, LOCATION)
values (10, 'ACCOUNTING', 'D10', 'NEW YORK');
  
insert into Department (DEPT_ID, DEPT_NAME, DEPT_NO, LOCATION)
values (20, 'RESEARCH', 'D20', 'DALLAS');
  
insert into Department (DEPT_ID, DEPT_NAME, DEPT_NO, LOCATION)
values (30, 'SALES', 'D30', 'CHICAGO');
  
insert into Department (DEPT_ID, DEPT_NAME, DEPT_NO, LOCATION)
values (40, 'OPERATIONS', 'D40', 'BOSTON');
  
-------------------------------------------------------------------------------------------------
  
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7839, 'KING', 'E7839', Str_To_Date('17-11-1981', '%d-%m-%Y'), 'PRESIDENT', 5000, 10, null);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7566, 'JONES', 'E7566', Str_To_Date('02-04-1981', '%d-%m-%Y'), 'MANAGER', 2975, 20, 7839);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7902, 'FORD', 'E7902', Str_To_Date('03-12-1981', '%d-%m-%Y'), 'ANALYST', 3000, 20, 7566);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7369, 'SMITH', 'E7369', Str_To_Date('17-12-1980', '%d-%m-%Y'), 'CLERK', 800, 20, 7902);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7698, 'BLAKE', 'E7698', Str_To_Date('01-05-1981', '%d-%m-%Y'), 'MANAGER', 2850, 30, 7839);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7499, 'ALLEN', 'E7499', Str_To_Date('20-02-1981', '%d-%m-%Y'), 'SALESMAN', 1600, 30, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7521, 'WARD', 'E7521', Str_To_Date('22-02-1981', '%d-%m-%Y'), 'SALESMAN', 1250, 30, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7654, 'MARTIN', 'E7654', Str_To_Date('28-09-1981', '%d-%m-%Y'), 'SALESMAN', 1250, 30, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7782, 'CLARK', 'E7782', Str_To_Date('09-06-1981', '%d-%m-%Y'), 'MANAGER', 2450, 30, 7839);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7788, 'SCOTT', 'E7788', Str_To_Date('19-04-1987', '%d-%m-%Y'), 'ANALYST', 3000, 20, 7566);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7844, 'TURNER', 'E7844', Str_To_Date('08-09-1981', '%d-%m-%Y'), 'SALESMAN', 1500, 30, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7876, 'ADAMS', 'E7876', Str_To_Date('23-05-1987', '%d-%m-%Y'), 'CLERK', 1100, 20, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7900, 'ADAMS', 'E7900', Str_To_Date('03-12-1981', '%d-%m-%Y'), 'CLERK', 950, 30, 7698);
  
insert into Employee (EMP_ID, EMP_NAME, EMP_NO, HIRE_DATE, JOB, SALARY, DEPT_ID, MNG_ID)
values (7934, 'MILLER', 'E7934', Str_To_Date('23-01-1982', '%d-%m-%Y'), 'CLERK', 1300, 10, 7698);
  
-------------------------------------------------------------------------------------------------
  
insert into Salary_Grade (GRADE, HIGH_SALARY, LOW_SALARY)
values (1, 9999, 3001);

3. 創(chuàng)建Maven項目和聲明庫

在這里公般,創(chuàng)建一個Maven項目并在pom.xml中聲明使用的Hibernate庫万搔。打開 Eclipse,選擇菜單 File -> New -> Other...官帘,在彈出框中選擇 Maven瞬雹,如下所示 -

下一步選擇工作目錄,如下圖所示 -

下一步刽虹,選擇模板類型挖炬,如下圖所示 -

下一步,寫入工程名稱:HibernateQuickStart状婶,以及輸入包信息:com.yiibai 等信息。

項目(HibernateQuickStart)創(chuàng)建完成后馅巷,如下圖所示 -

pom.xml中膛虫,需要聲明使用Hibernate 5庫,以及用于各種數(shù)據(jù)庫類型(如Oracle钓猬,MySQL和SQL Server)的JDBC庫稍刀,這里使用 MySQL JDBC。

完整的 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>com.yiibai</groupId>
    <artifactId>HibernateQuickStart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

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

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

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

        <!-- Hibernate Core -->
        <!-- http://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>

        <!-- 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>

4. 實體類

在這一步中敞曹,我們來創(chuàng)建實體類账月。每個實體描述一個數(shù)據(jù)庫中的表。這里先不說明每個類是做什么用的澳迫。一共要創(chuàng)建如下幾個實體類(對應(yīng)上面創(chuàng)建的四張表)局齿,如下 -

  • Department.java
  • Employee.java
  • SalaryGrade.java
  • Timekeeper.java

所有創(chuàng)建的類如下圖所示 -

這幾個類的代碼,分別如下所示 -

Department.java 類代碼 -

package com.yiibai.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 com.yiibai.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 com.yiibai.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 com.yiibai.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;
    }

}

5. 配置hibernate

配置hibernate目的是讓Hibernate可以連接數(shù)據(jù)庫并與數(shù)據(jù)庫交互橄登,并聲明在前面的步驟中創(chuàng)建的實體列表抓歼。

src/main/java中創(chuàng)建一個名稱為:hibernate.cfg.xml 的配置文件讥此,當(dāng)前項目結(jié)構(gòu)如下圖所示 -

hibernate.cfg.xml 配置文件的內(nèi)容如下所示 -

<?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://localhost:3306/mydb?serverTimezone=UTC</property>
      <property name="connection.username">root</property>
      <property name="connection.password">123456</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="com.yiibai.entities.Department" />
      <mapping class="com.yiibai.entities.Employee" />
      <mapping class="com.yiibai.entities.SalaryGrade" />
      <mapping class="com.yiibai.entities.Timekeeper" />
 
  </session-factory>
 
</hibernate-configuration>

每種數(shù)據(jù)庫都有一個單獨的方言, 例如:

Oracle方言:

  • org.hibernate.dialect.Oracle10gDialect(Dùngcho 10g&11g)
  • org.hibernate.dialect.Oracle12cDialect

SQL Server方言:

  • org.hibernate.dialect.SQLServerDialect并
  • org.hibernate.dialect.SQLServer2012Dialect
  • org.hibernate.dialect.SQLServer2008Dialect

MySQL方言

  • org.hibernate.dialect.MySQLDialect
  • org.hibernate.dialect.MySQL5Dialect

什么是方言谣妻?

Dialect是一個使用Hibernate的方式將數(shù)據(jù)庫的數(shù)據(jù)類型轉(zhuǎn)換為Java的數(shù)據(jù)類型萄喳,反之亦然。此外蹋半,它用于定義將HSQL(Hibernate SQL)的函數(shù)轉(zhuǎn)換為數(shù)據(jù)中的函數(shù)的方式他巨,如下列出的一部分 -

Java SQL類型 Oracle MySQL SQL Server
Types.BIT number(1,0) bit bit
Types.BIGINT number(19,0) bigin bigint
Types.DATE date date date
....... ... ... ...
Types.CLOB clob longtext varchar(MAX)
Types.BLOB blob longblob varbinary(MAX)

6. SessionFactory

創(chuàng)建一個文件: HibernateUtils.java , 其代碼如下 -


7. Hibernate查詢語言(HQL)

Hibernate使用Hibernate查詢語言(HQL)查詢數(shù)據(jù)减江。 HQL與我們所了解的數(shù)據(jù)庫SQL語句有點不同染突。

SQL:

  • 在表中查詢數(shù)據(jù)

HQL:

  • 在實體類中查詢對象數(shù)據(jù)

參考比較以下用法 -

-- 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;

Hibernate的操作規(guī)則:

應(yīng)用程序編寫的HQL在操作過程中,Hibernate本身就意識到它使用的數(shù)據(jù)庫類型(如:MySQL)您市,它會自動將HQL轉(zhuǎn)換為等價的數(shù)據(jù)庫類型的SQL形式觉痛。 事實上,各種類型的數(shù)據(jù)庫之間的SQL語法有一些差異茵休,比如:返回記錄的行數(shù)的限制就不同(MySQL中使用 limit 子句)薪棒。

可以參考HQL語法: http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/queryhql.html

8. 使用Hibernate查詢數(shù)據(jù)

在Hibernate中有很多方法可以用來查詢數(shù)據(jù)。在這部分中榕莺,將介紹一些查詢數(shù)據(jù)的典型方法俐芯。

8.1 - 使用HQL的查詢對象

查詢對象示例-1
第一個例子,使用HQL查詢對象(Entity)钉鸯,創(chuàng)建一個Java類文件:QueryObjectDemo.java吧史,其代碼如下 -

package com.yiibai;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
       }
   }
    
}

運行上面代碼,得到以下結(jié)果 -

查詢對象示例-2

創(chuàng)建一個Java類文件:QueryObjectDemo2.java唠雕,其代碼如下 -

package com.yiibai;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
        }
    }
}

運行上面代碼贸营,得到以下結(jié)果 -

......
org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select employee0_.EMP_ID ..._NO=?
Emp: E7839 : KING
Emp: E7934 : MILLER

8.2 - 使用HQL查詢讀取多列數(shù)據(jù)

創(chuàng)建一個Java類文件:QuerySomeColumnDemo.java,其代碼如下 -

package com.yiibai;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
        }
  
    }
}

運行上面代碼岩睁,得到以下結(jié)果 -

Hibernate: select employee0_.EMP_ID..._0_ from EMPLOYEE employee0_
Emp Id: 7369
    Emp No: E7369
    Emp Name: SMITH
Emp Id: 7499
    Emp No: E7499
    Emp Name: ALLEN
Emp Id: 7521
    Emp No: E7521
    Emp Name: WARD
Emp Id: 7566
    Emp No: E7566
    Emp Name: JONES
Emp Id: 7654
    Emp No: E7654
    Emp Name: MARTIN
Emp Id: 7698
    Emp No: E7698
    Emp Name: BLAKE
Emp Id: 7782
    Emp No: E7782
    Emp Name: CLARK
Emp Id: 7788
    Emp No: E7788
    Emp Name: SCOTT
Emp Id: 7839
    Emp No: E7839
    Emp Name: KING
Emp Id: 7844
    Emp No: E7844
    Emp Name: TURNER
Emp Id: 7876
    Emp No: E7876
    Emp Name: ADAMS
Emp Id: 7900
    Emp No: E7900
    Emp Name: ADAMS
Emp Id: 7902
    Emp No: E7902
    Emp Name: FORD
Emp Id: 7934
    Emp No: E7934
    Emp Name: MILLER

8.3 - 使用HQL和JavaBean查詢多列數(shù)據(jù)

在這種情況下钞脂,如果需要在某些表中提取某些列的數(shù)據(jù),最好的方法是使用Java bean捕儒。使用Java bean的構(gòu)造函數(shù)來為不同的字段設(shè)置值冰啃。在此構(gòu)造函數(shù)加入HQL查詢。

創(chuàng)建一個Java類文件:ShortEmpInfo.java刘莹,其代碼如下 -

package com.yiibai;

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;
    }

}

創(chuàng)建一個Java類文件:ShortEmpInfoQueryDemo.java阎毅,其代碼如下 -

package com.yiibai;

import java.util.List;

import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
        }
    }
     
}

運行上面代碼,得到以下結(jié)果 -

8.4 - 查詢檢索唯一結(jié)果

創(chuàng)建一個Java類文件:UniqueResultDemo.java点弯,其代碼如下 -

package com.yiibai;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;

import com.yiibai.entities.Department;
import com.yiibai.entities.Employee;

 
public class UniqueResultDemo {
 
    public static Department getDepartment(Session session, String deptNo) {
        String sql = "Select d from " + Department.class.getName() + " d "http://
                + " 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 "http://
                + " 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();
        }
    }
     
}

運行上面代碼扇调,得到以下結(jié)果 -

9. Hibernate瞬態(tài),持久和分離

在這部分中抢肛,使用Session.persist(Object)將瞬態(tài)對象插入數(shù)據(jù)庫的簡單示例肃拜。本例中將介紹對象瞬態(tài)(Transitent)痴腌,持久(Persistent)和分離(Detached)的概念。

創(chuàng)建一個Java類文件:DataUtils.java燃领,其代碼如下 -

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.query.Query;
import com.yiibai.entities.Department;
import com.yiibai.entities.Employee;
 
public class DataUtils {
 
   public static Department findDepartment(Session session, String deptNo) {
       String sql = "Select d from " + Department.class.getName() + " d "http://
               + " 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 "http://
               + " Where e.empNo = :empNo";
       Query<Employee> query = session.createQuery(sql);
       query.setParameter("empNo", empNo);
       return query.getSingleResult();
   }
 
}

創(chuàng)建一個Java類文件:PersistDemo.java士聪,其代碼如下 -

package com.yiibai;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.entities.Department;
import com.yiibai.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());
        
   }
    
}

運行上面代碼,得到以下結(jié)果 -

10. Hibernate生命周期

Hibernate的Session類的有一些/幾組的重要方法猛蔽,如下圖所示:

Hibernate中的一個對象存在于以下四個狀態(tài)之中的一種:

  • 短暫(Transient)
  • 持久(Persistent)
  • Removed
  • Detached

以上幾個狀態(tài)在下面圖中解釋:

下面來看這幾個狀態(tài)的流轉(zhuǎn)說明 -

  1. 當(dāng)從一個實體創(chuàng)建一個新的Java對象時剥悟,該對象處于“短暫”狀態(tài)。 Hibernate不知道它的存在曼库,因為它獨立于Hibernate的管理区岗。

  2. 如果使用方法:getloadfind獲取實體對象毁枯,則將獲得一個等同于數(shù)據(jù)庫中的1條記錄的對象慈缔。 此對象處于Persistent狀態(tài)。 它由Hibernate管理种玛。

  3. 會話調(diào)用方法:save藐鹤,saveOrUpdatepersist。 合并將短暫(Transient)對象置于Hibernate的管理之下赂韵,此對象轉(zhuǎn)為持久化(Persistent)狀態(tài)娱节。 在使用的具體情況下,它向數(shù)據(jù)庫插入或更新數(shù)據(jù)祭示。

  4. Session調(diào)用evict(..)clear()肄满,以便從處于Hibernate管理狀態(tài)的對象處于關(guān)閉狀態(tài),并且這些對象處于分離(Detached)的狀態(tài)质涛。

  5. 使用update(..)稠歉,saveOrUpdate(..)merge(..)將有助于重新連接分離對象汇陆。 在具體情況下轧抗,它會向數(shù)據(jù)庫中創(chuàng)建更新或插入數(shù)據(jù)。 對象轉(zhuǎn)回持久化(Persistent)狀態(tài)瞬测。

  6. Session調(diào)用方法:remove(..)delete(..)刪除除記錄并持久化對象纠炮。

11. 用Hibernate插入捕捂,更新运褪,刪除

11.1 - 持久化(Persistent)

當(dāng)一個對像使用 Sessionget(),load(),find()方法獲取關(guān)聯(lián)數(shù)據(jù)時,它處于持久化(Persistent)狀態(tài)。

創(chuàng)建一個JAVA類文件:PersistentDemo.java怀大,用于演示對象的持久化(Persistent)狀態(tài)。

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.entities.Department;
import com.yiibai.entities.Employee;
 
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();
       }
   }
    
}

執(zhí)行上面代碼八孝,得到以下結(jié)果 -

11.2 - 瞬態(tài)轉(zhuǎn)為持久化狀態(tài)

11.3 - 瞬態(tài)轉(zhuǎn)為持久化狀態(tài):使用persist(Object)

創(chuàng)建一個JAVA類文件:PersistTransientDemo.java,用于演示對象的持久化(Persistent)狀態(tài)问潭。

package com.yiibai;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Employee;
import com.yiibai.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();
       }
   }
    
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.4 - 瞬態(tài)轉(zhuǎn)為持久化狀態(tài):使用save(Object)

創(chuàng)建一個JAVA類文件:SaveTransientDemo.java婚被,用于演示對象的持久化(Persistent)狀態(tài)狡忙。

package com.yiibai;

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 com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Employee;
import com.yiibai.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();
       }
   }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.5 - 瞬態(tài)轉(zhuǎn)為持久化狀態(tài):使用saveOrUpdate(Object)

創(chuàng)建一個JAVA類文件:SaveOrUpdateTransientDemo.java址芯,用于演示對象的持久化(Persistent)狀態(tài)灾茁。

package com.yiibai;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Employee;
import com.yiibai.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();
       }
   }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.6 - 瞬態(tài)轉(zhuǎn)為持久化狀態(tài):使用merge(Object)

創(chuàng)建一個JAVA類文件:MergeTransientDemo.java谷炸,用于演示對象的持久化(Persistent)狀態(tài)北专。

package com.yiibai;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Employee;
import com.yiibai.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();
       }
   }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.7 - 持久化轉(zhuǎn)變?yōu)榉蛛x狀態(tài)

由Hibernate管理的持久化(Persistent)條件中的一個對象可以通過以下兩個Session的方法轉(zhuǎn)換為Detached(獨立于Hibernate的管理)狀態(tài):

  • evict (Object) - 從Hibernate管理中刪除一個對象

  • clear() - 從Hibernate管理的對象中刪除所有對象旬陡。

當(dāng)然拓颓,當(dāng)Session調(diào)用順序為:commit()close()rollback()時描孟,當(dāng)前會話已經(jīng)完成驶睦。 此會話的所有Persistence對象將從新打開的會話中分離。

創(chuàng)建一個JAVA類文件:EvictDemo.java画拾,用于演示對象持久化轉(zhuǎn)變?yōu)榉蛛x狀態(tài)啥繁。

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
       }
   }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

創(chuàng)建一個JAVA類文件:ClearDemo.java青抛,用于演示將所有對象持久化轉(zhuǎn)變?yōu)榉蛛x狀態(tài)旗闽。

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Department;
import com.yiibai.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();
       }
   }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.8 - 分離狀態(tài)轉(zhuǎn)變?yōu)槌志没癄顟B(tài)

Hibernate管理分離的對象可以通過以下Session的一些方法重新附加:

  • update(Object)
  • saveOrUpdate(Object)
  • merge(Object)
  • refresh(Object)
  • lock(Object)

可以在以下示例中看到這些方法的區(qū)別:

11.9-分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài):使用update(Object)

創(chuàng)建一個JAVA類文件:UpdateDetachedDemo.java蜜另,用于演示將對象分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài)适室。

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.entities.Department;
import com.yiibai.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();
        }

    }
}

執(zhí)行上面代碼,得到以下結(jié)果 -

11.10 - 分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài):使用saveOrUpdate(Object)

創(chuàng)建一個JAVA類文件:SaveOrUpdateDetachedDemo.java举瑰,用于演示將對象分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài)捣辆。

package com.yiibai;

import java.util.Random;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
       }
 
   }
 
}

執(zhí)行上面代碼,多幾次運行示例錯碼此迅,可以看到兩種情況汽畴,saveOrUpdate()方法調(diào)用在數(shù)據(jù)上插入或更新。得到以下結(jié)果 -

11.11-分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài):使用merge(Object)

Hibernate 2版本有saveOrUpdateCopy(Object)方法耸序。從Hibernate 3起忍些,它被重命名為merge(Object)。 因此與saveOrUpdate()相比坎怪,merge()方法有一些相似性和差異罢坝。

merge(Object)不會將對象置于Hibernate的管理下,而是創(chuàng)建一個對象的副本搅窿,而不是管理該對象嘁酿。

如果調(diào)用saveOrUpdate(aObject)aObject由Hibernate管理隙券,并且與aObject具有相同的ID將會拋出異常,但是使用merge(aObject)時不會得到此異常闹司。

創(chuàng)建一個JAVA類文件:MergeDetachedDemo.java娱仔,用于演示將對象分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài)。

package com.yiibai;

import java.util.Random;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
       }
 
   }
 
}

執(zhí)行上面代碼开仰,多幾次運行示例錯碼拟枚,可以看到兩種情況,得到以下結(jié)果 -

11.12 - 分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài):使用refresh(Object)

創(chuàng)建一個JAVA類文件:RefreshDetachedDemo.java众弓,用于演示將對象分離轉(zhuǎn)變?yōu)槌志眯誀顟B(tài)恩溅。

package com.yiibai;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.yiibai.DataUtils;
import com.yiibai.HibernateUtils;
import com.yiibai.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();
       }
 
   }
 
}

執(zhí)行上面代碼,多幾次運行示例錯碼谓娃,可以看到兩種情況脚乡,得到以下結(jié)果 -

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市滨达,隨后出現(xiàn)的幾起案子奶稠,更是在濱河造成了極大的恐慌,老刑警劉巖捡遍,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锌订,死亡現(xiàn)場離奇詭異,居然都是意外死亡画株,警方通過查閱死者的電腦和手機辆飘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谓传,“玉大人蜈项,你說我怎么就攤上這事⌒” “怎么了紧卒?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诗祸。 經(jīng)常有香客問我跑芳,道長,這世上最難降的妖魔是什么直颅? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任博个,我火速辦了婚禮,結(jié)果婚禮上际乘,老公的妹妹穿的比我還像新娘。我一直安慰自己漂佩,他們只是感情好脖含,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布罪塔。 她就那樣靜靜地躺著,像睡著了一般养葵。 火紅的嫁衣襯著肌膚如雪征堪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天关拒,我揣著相機與錄音佃蚜,去河邊找鬼。 笑死着绊,一個胖子當(dāng)著我的面吹牛谐算,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播归露,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼洲脂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剧包?” 一聲冷哼從身側(cè)響起恐锦,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疆液,沒想到半個月后一铅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡堕油,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年潘飘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馍迄。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡福也,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出攀圈,到底是詐尸還是另有隱情暴凑,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布赘来,位于F島的核電站现喳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏犬辰。R本人自食惡果不足惜嗦篱,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幌缝。 院中可真熱鬧灸促,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至典鸡,卻和暖如春被廓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萝玷。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工嫁乘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人球碉。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓蜓斧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親汁尺。 傳聞我的和親對象是個殘疾皇子法精,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一、概述 Hibernate是一種對象/關(guān)系映射的解決方案痴突,就是將Java中對象與對象之間的關(guān)系映射至關(guān)系數(shù)據(jù)庫中...
    凜_冬_將_至閱讀 585評論 0 0
  • 本文中我們介紹并比較兩種最流行的開源持久框架:iBATIS和Hibernate辽装,我們還會討論到Java Persi...
    大同若魚閱讀 4,310評論 4 27
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法帮碰,類相關(guān)的語法,內(nèi)部類的語法拾积,繼承相關(guān)的語法殉挽,異常的語法,線程的語...
    子非魚_t_閱讀 31,624評論 18 399
  • 好像是大學(xué)時候看的《擺渡人》的小說拓巧,為小玉的勇敢感動斯碌,也為她的付出心酸。還記得那個場景肛度,小玉點點頭傻唾,低聲說:“我不...
    臨江越閱讀 322評論 1 0
  • 一項新的學(xué)習(xí)項目,我們可能會去策劃學(xué)習(xí)方法承耿,準備學(xué)習(xí)資料冠骄,規(guī)劃尋找學(xué)習(xí)時間等等,而學(xué)習(xí)本身卻遲遲未行加袋,被無限期拖延...
    隨意咖啡閱讀 258評論 0 0