Hibernate快速入门 您所在的位置:网站首页 hibernate怎么读 Hibernate快速入门

Hibernate快速入门

#Hibernate快速入门 | 来源: 网络整理| 查看: 265

Hibernate是一个开源,轻量级的ORM(对象关系映射)工具。Hibernate框架简化了java应用程序与数据库交互的开发。

ORM工具简化了数据创建,数据处理和数据访问。它是将对象映射到数据库中存储的数据(表)的编程技术。

注:为什么会有这篇教程文章?答:只是想写一篇最NB的Hibernate教程入门文章。NB代表人见人爱,花见花开,车见爆胎,飞鸟落地…,最后,需要注意的是:这篇文章包教不包会!除非你从头到尾认真看完并运行所有示例代码。

1. Hibernate快速入门简介

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

Hibernate 5.2.2.FinalEclipse 4.6 (MARS)

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

从Hibernate 5.0开始Hibernate Spatial是Hibernate项目的一部分,因此我们也可以处理GIS数据了。

域模型映射支持Java 8日期和时间类型。 标准SQL日期/时间类型以及支持的Java 8 Date / Time类类型之间的映射,如下所示:

DATE: java.time.LocalDateTIME: java.time.LocalTime, java.time.OffsetTimeTIMESTAMP: java.time.Instant, java.time.LocalDateTime,java.time.OffsetDateTime 和 java.time.ZonedDateTime

字节码增强机制从头重新设计,Hibernate可支持Maven和Gradle插件。可以通过字节码仪器来增强三个主要方面:

懒初始化:字段可以声明为LAZY,只有在第一次被访问时,它们才被提取。脏检查:实体被增强,使得它们可以跟踪在持久化上下文中加载之后变化的所有属性。双向关联:即使开发人员仅更新单侧,但也可以自动同步双向关联的双方。

Hibernate的原生API(Session等)已更新为使用泛型类型化。无需在获取实体时转换。

Hibernate 5.0将其扩展到更广泛的类型(例如UUID)。引用二级缓存,使实体引用能够直接存储到第二级缓存中(用于不可变实体)。 2. 准备数据库

Hibernate是一个库,为了处理所有类型的数据库,它不依赖于应用程序选择的任何类型的数据库,如果Java是“一次写入到处运行”的语言,Hibernate则是“写一次就可运行在所有类型的数据库“中的框架。

在这篇文章中,使用的是MySQL数据(你可使用其它的数据库,如:Oracle,MySQL或SQL Server),并创建一个简单的数据库:mydb,完整的数据库创建语句如下所示:

创建数据:

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

需要创建以下几张表,它们的关系图如下所示 -

创建表语句:

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

向上面创建的表中,分别插入一些测试数据,如下所示 -

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. 创建Maven项目和声明库

在这里,创建一个Maven项目并在pom.xml中声明使用的Hibernate库。打开 Eclipse,选择菜单 File -> New -> Other…,在弹出框中选择 Maven,如下所示 -

下一步选择工作目录,如下图所示 -

下一步,选择模板类型,如下图所示 -

下一步,写入工程名称:HibernateQuickStart,以及输入包信息:com.yiibai 等信息。

项目(HibernateQuickStart)创建完成后,如下图所示 -

在pom.xml中,需要声明使用Hibernate 5库,以及用于各种数据库类型(如Oracle,MySQL和SQL Server)的JDBC库,这里使用 MySQL JDBC。

完整的 pom.xml 配置/声明如下所示 -

4.0.0 com.yiibai HibernateQuickStart 0.0.1-SNAPSHOT jar HibernateQuickStart http://maven.apache.org UTF-8 junit junit 3.8.1 test org.hibernate hibernate-core 5.2.2.Final mysql mysql-connector-java 5.1.34 net.sourceforge.jtds jtds 1.3.1 4. 实体类

在这一步中,我们来创建实体类。每个实体描述一个数据库中的表。这里先不说明每个类是做什么用的。一共要创建如下几个实体类(对应上面创建的四张表),如下 -

Department.javaEmployee.javaSalaryGrade.javaTimekeeper.java

所有创建的类如下图所示 -

这几个类的代码,分别如下所示 -

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 employees = new HashSet(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 getEmployees() { return employees; } public void setEmployees(Set 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 employees = new HashSet(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 getEmployees() { return employees; } public void setEmployees(Set 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可以连接数据库并与数据库交互,并声明在前面的步骤中创建的实体列表。

在src/main/java中创建一个名称为:hibernate.cfg.xml 的配置文件,当前项目结构如下图所示 -

hibernate.cfg.xml 配置文件的内容如下所示 -

com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC root 123456 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.internal.NoCacheProvider true

每种数据库都有一个单独的方言, 例如:

Oracle方言:

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

SQL Server方言:

org.hibernate.dialect.SQLServerDialect并org.hibernate.dialect.SQLServer2012Dialectorg.hibernate.dialect.SQLServer2008Dialect

MySQL方言

org.hibernate.dialect.MySQLDialectorg.hibernate.dialect.MySQL5Dialect 什么是方言?

Dialect是一个使用Hibernate的方式将数据库的数据类型转换为Java的数据类型,反之亦然。此外,它用于定义将HSQL(Hibernate SQL)的函数转换为数据中的函数的方式,如下列出的一部分 -

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

创建一个文件: HibernateUtils.java , 其代码如下 -

7. Hibernate查询语言(HQL)

Hibernate使用Hibernate查询语言(HQL)查询数据。 HQL与我们所了解的数据库SQL语句有点不同。

SQL:

在表中查询数据

HQL:

在实体类中查询对象数据

参考比较以下用法 -

-- 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的操作规则:

应用程序编写的HQL在操作过程中,Hibernate本身就意识到它使用的数据库类型(如:MySQL),它会自动将HQL转换为等价的数据库类型的SQL形式。 事实上,各种类型的数据库之间的SQL语法有一些差异,比如:返回记录的行数的限制就不同(MySQL中使用 limit 子句)。

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

8. 使用Hibernate查询数据

在Hibernate中有很多方法可以用来查询数据。在这部分中,将介绍一些查询数据的典型方法。

8.1 - 使用HQL的查询对象

查询对象示例-1第一个例子,使用HQL查询对象(Entity),创建一个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 query = session.createQuery(sql); // Execute query. List 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(); } } }

运行上面代码,得到以下结果 -

查询对象示例-2

创建一个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 query = session.createQuery(sql); query.setParameter("deptNo", "D10"); // Execute query. List 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(); } } }

运行上面代码,得到以下结果 -

...... 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查询读取多列数据

创建一个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 query = session.createQuery(sql); // Execute Query. // Get the array of Object List 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(); } } }

运行上面代码,得到以下结果 -

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查询多列数据

在这种情况下,如果需要在某些表中提取某些列的数据,最好的方法是使用Java bean。使用Java bean的构造函数来为不同的字段设置值。在此构造函数加入HQL查询。

创建一个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; } }

创建一个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 query = session.createQuery(sql); // Execute query. // Get a List of ShortEmpInfo List 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(); } } }

运行上面代码,得到以下结果 -

8.4 - 查询检索唯一结果

创建一个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 "// + " where d.deptNo= :deptNo "; Query 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 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 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(); } } }

运行上面代码,得到以下结果 -

9. Hibernate瞬态,持久和分离

在这部分中,使用Session.persist(Object)将瞬态对象插入数据库的简单示例。本例中将介绍对象瞬态(Transitent),持久(Persistent)和分离(Detached)的概念。

创建一个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 "// + " Where d.deptNo = :deptNo"; Query 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 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 query = session.createQuery(sql); query.setParameter("empNo", empNo); return query.getSingleResult(); } }

创建一个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()); } }

运行上面代码,得到以下结果 -

10. Hibernate生命周期

Hibernate的Session类的有一些/几组的重要方法,如下图所示:

Hibernate中的一个对象存在于以下四个状态之中的一种:

短暂(Transient)持久(Persistent)RemovedDetached

以上几个状态在下面图中解释:

下面来看这几个状态的流转说明 -

当从一个实体创建一个新的Java对象时,该对象处于“短暂”状态。 Hibernate不知道它的存在,因为它独立于Hibernate的管理。

如果使用方法:get,load或find获取实体对象,则将获得一个等同于数据库中的1条记录的对象。 此对象处于Persistent状态。 它由Hibernate管理。

会话调用方法:save,saveOrUpdate和persist。 合并将短暂(Transient)对象置于Hibernate的管理之下,此对象转为持久化(Persistent)状态。 在使用的具体情况下,它向数据库插入或更新数据。

Session调用evict(..)或clear(),以便从处于Hibernate管理状态的对象处于关闭状态,并且这些对象处于分离(Detached)的状态。

使用update(..),saveOrUpdate(..),merge(..)将有助于重新连接分离对象。 在具体情况下,它会向数据库中创建更新或插入数据。 对象转回持久化(Persistent)状态。

Session调用方法:remove(..),delete(..)删除除记录并持久化对象。

11. 用Hibernate插入,更新,删除11.1 - 持久化(Persistent)

当一个对像使用 Session 的get(),load(),find()方法获取关联数据时,它处于持久化(Persistent)状态。

创建一个JAVA类文件:PersistentDemo.java,用于演示对象的持久化(Persistent)状态。

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

执行上面代码,得到以下结果 -

11.2 - 瞬态转为持久化状态

11.3 - 瞬态转为持久化状态:使用persist(Object)

创建一个JAVA类文件:PersistTransientDemo.java,用于演示对象的持久化(Persistent)状态。

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

执行上面代码,得到以下结果 -

11.4 - 瞬态转为持久化状态:使用save(Object)

创建一个JAVA类文件:SaveTransientDemo.java,用于演示对象的持久化(Persistent)状态。

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

执行上面代码,得到以下结果 -

11.5 - 瞬态转为持久化状态:使用saveOrUpdate(Object)

创建一个JAVA类文件:SaveOrUpdateTransientDemo.java,用于演示对象的持久化(Persistent)状态。

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

执行上面代码,得到以下结果 -

11.6 - 瞬态转为持久化状态:使用merge(Object)

创建一个JAVA类文件:MergeTransientDemo.java,用于演示对象的持久化(Persistent)状态。

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

执行上面代码,得到以下结果 -

11.7 - 持久化转变为分离状态

由Hibernate管理的持久化(Persistent)条件中的一个对象可以通过以下两个Session的方法转换为Detached(独立于Hibernate的管理)状态:

evict (Object) - 从Hibernate管理中删除一个对象

clear() - 从Hibernate管理的对象中删除所有对象。

当然,当Session调用顺序为:commit(),close()或rollback()时,当前会话已经完成。 此会话的所有Persistence对象将从新打开的会话中分离。

创建一个JAVA类文件:EvictDemo.java,用于演示对象持久化转变为分离状态。

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

执行上面代码,得到以下结果 -

创建一个JAVA类文件:ClearDemo.java,用于演示将所有对象持久化转变为分离状态。

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

执行上面代码,得到以下结果 -

11.8 - 分离状态转变为持久化状态

Hibernate管理分离的对象可以通过以下Session的一些方法重新附加:

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

可以在以下示例中看到这些方法的区别:

11.9-分离转变为持久性状态:使用update(Object)

创建一个JAVA类文件:UpdateDetachedDemo.java,用于演示将对象分离转变为持久性状态。

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

执行上面代码,得到以下结果 -

11.10 - 分离转变为持久性状态:使用saveOrUpdate(Object)

创建一个JAVA类文件:SaveOrUpdateDetachedDemo.java,用于演示将对象分离转变为持久性状态。

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

执行上面代码,多几次运行示例错码,可以看到两种情况,saveOrUpdate()方法调用在数据上插入或更新。得到以下结果 -

11.11-分离转变为持久性状态:使用merge(Object)

Hibernate 2版本有saveOrUpdateCopy(Object)方法。从Hibernate 3起,它被重命名为merge(Object)。 因此与saveOrUpdate()相比,merge()方法有一些相似性和差异。

merge(Object)不会将对象置于Hibernate的管理下,而是创建一个对象的副本,而不是管理该对象。

如果调用saveOrUpdate(aObject)则aObject由Hibernate管理,并且与aObject具有相同的ID将会抛出异常,但是使用merge(aObject)时不会得到此异常。

创建一个JAVA类文件:MergeDetachedDemo.java,用于演示将对象分离转变为持久性状态。

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

执行上面代码,多几次运行示例错码,可以看到两种情况,得到以下结果 -

11.12 - 分离转变为持久性状态:使用refresh(Object)

创建一个JAVA类文件:RefreshDetachedDemo.java,用于演示将对象分离转变为持久性状态。

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

执行上面代码,多几次运行示例错码,可以看到两种情况,得到以下结果 -

以下是纠正/补充内容: HibernateUtils.java类,无代码显示以下为乱码,凑够字数...线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的  提交时间:2019-09-04

  

上一篇: Hibernate二级缓存 下一篇:哥,这回真没有了


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有