Hibernate 专题
专题目录
您的位置:java > Hibernate 专题 > Hibernate快速入门
Hibernate快速入门
作者:--    发布时间:2019-11-20

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

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

注:为什么会有这篇教程文章?答:只是想写一篇最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数据了。

  2. 域模型映射支持java 8日期和时间类型。 标准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
  3. 字节码增强机制从头重新设计,hibernate可支持maven和gradle插件。可以通过字节码仪器来增强三个主要方面:

    • 懒初始化:字段可以声明为lazy,只有在第一次被访问时,它们才被提取。
    • 脏检查:实体被增强,使得它们可以跟踪在持久化上下文中加载之后变化的所有属性。
    • 双向关联:即使开发人员仅更新单侧,但也可以自动同步双向关联的双方。
  4. hibernate的原生api(session等)已更新为使用泛型类型化。无需在获取实体时转换。

  5. hibernate 5.0将其扩展到更广泛的类型(例如uuid)。
  6. 引用二级缓存,使实体引用能够直接存储到第二级缓存中(用于不可变实体)。

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.h3 等信息。

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

pom.xml中,需要声明使用hibernate 5库,以及用于各种数据库类型(如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.h3</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. 实体类

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

  • department.java
  • employee.java
  • salarygrade.java
  • timekeeper.java

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

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

department.java 类代码 -

package com.h3.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.h3.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.h3.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.h3.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 配置文件的内容如下所示 -

<?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.h3.entities.department" />
      <mapping class="com.h3.entities.employee" />
      <mapping class="com.h3.entities.salarygrade" />
      <mapping class="com.h3.entities.timekeeper" />

  </session-factory>

</hibernate-configuration>

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

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的方式将数据库的数据类型转换为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.h3;

import java.util.list;

import org.hibernate.query.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.hibernateutils;
import com.h3.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();
       }
   }

}

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

查询对象示例-2

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

package com.h3;

import java.util.list;

import org.hibernate.query.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.hibernateutils;
import com.h3.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();
        }
    }
}

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

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

import java.util.list;

import org.hibernate.query.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.hibernateutils;
import com.h3.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();
        }

    }
}

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

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

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

import java.util.list;

import org.hibernate.query.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.hibernateutils;
import com.h3.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();
        }
    }

}

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

8.4 - 查询检索唯一结果

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

package com.h3;

import java.util.set;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import org.hibernate.query.query;

import com.h3.entities.department;
import com.h3.entities.employee;


public class uniqueresultdemo {

    public static department getdepartment(session session, string deptno) {
        string sql = "select d from " + department.class.getname() + " d "//
                + " where d.deptno= :deptno ";
        query<department> query = session.createquery(sql);
        query.setparameter("deptno", deptno);
        return (department) query.getsingleresult();
    }

    public static employee getemployee(session session, long empid) {
        string sql = "select e from " + employee.class.getname() + " e "//
                + " where e.empid= :empid ";
        query<employee> query = session.createquery(sql);
        query.setparameter("empid", empid);
        return (employee) query.getsingleresult();
    }

    public static void main(string[] args) {
        sessionfactory factory = hibernateutils.getsessionfactory();

        session session = factory.getcurrentsession();

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

            department dept = getdepartment(session, "d10");
            set<employee> emps = dept.getemployees();

            system.out.println("dept name: " + dept.getdeptname());
            for (employee emp : emps) {
                system.out.println(" emp name: " + emp.getempname());
            }

            employee emp = getemployee(session, 7839l);
            system.out.println("emp name: " + emp.getempname());

            session.gettransaction().commit();
        } catch (exception e) {
            e.printstacktrace();
            session.gettransaction().rollback();
        }
    }

}

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

9. hibernate瞬态,持久和分离

在这部分中,使用session.persist(object)将瞬态对象插入数据库的简单示例。本例中将介绍对象瞬态(transitent),持久(persistent)和分离(detached)的概念。

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

package com.h3;

import org.hibernate.session;
import org.hibernate.query.query;
import com.h3.entities.department;
import com.h3.entities.employee;

public class datautils {

   public static department finddepartment(session session, string deptno) {
       string sql = "select d from " + department.class.getname() + " d "//
               + " where d.deptno = :deptno";
       query<department> query = session.createquery(sql);
       query.setparameter("deptno", deptno);
       return query.getsingleresult();
   }

   public static long getmaxempid(session session) {
       string sql = "select max(e.empid) from " + employee.class.getname() + " e ";
       query<number> query = session.createquery(sql);
       number value = query.getsingleresult();
       if (value == null) {
           return 0l;
       }
       return value.longvalue();
   }

   public static employee findemployee(session session, string empno) {
       string sql = "select e from " + employee.class.getname() + " e "//
               + " where e.empno = :empno";
       query<employee> query = session.createquery(sql);
       query.setparameter("empno", empno);
       return query.getsingleresult();
   }

}

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

package com.h3;

import java.util.date;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.entities.department;
import com.h3.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)
  • removed
  • detached

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

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

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

  2. 如果使用方法:getloadfind获取实体对象,则将获得一个等同于数据库中的1条记录的对象。 此对象处于persistent状态。 它由hibernate管理。

  3. 会话调用方法:savesaveorupdatepersist。 合并将短暂(transient)对象置于hibernate的管理之下,此对象转为持久化(persistent)状态。 在使用的具体情况下,它向数据库插入或更新数据。

  4. session调用evict(..)clear(),以便从处于hibernate管理状态的对象处于关闭状态,并且这些对象处于分离(detached)的状态。

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

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

11. 用hibernate插入,更新,删除

11.1 - 持久化(persistent)

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

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

package com.h3;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.entities.department;
import com.h3.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.h3;

import java.text.dateformat;
import java.text.simpledateformat;
import java.util.date;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.employee;
import com.h3.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.h3;

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.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.employee;
import com.h3.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.h3;

import java.text.dateformat;
import java.text.simpledateformat;
import java.util.date;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.employee;
import com.h3.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.h3;

import java.text.dateformat;
import java.text.simpledateformat;
import java.util.date;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.employee;
import com.h3.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.h3;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.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.h3;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.department;
import com.h3.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.h3;

import org.hibernate.session;
import org.hibernate.sessionfactory;

import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.entities.department;
import com.h3.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.h3;

import java.util.random;

import org.hibernate.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.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.h3;

import java.util.random;

import org.hibernate.query;
import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.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.h3;

import org.hibernate.session;
import org.hibernate.sessionfactory;
import com.h3.datautils;
import com.h3.hibernateutils;
import com.h3.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
网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册