举例:primary
2.1 定义持久化对象(PO)
package com.eason.hibernate.po;
public class Student {
//这里通常使用Integer而不是使用int,因为低版本框架底层可能使用null与id进行比较,如果使用int类型,则会出现错误
private Integer id;
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", score=" + score + "]";
}
}
2.2 配置映射文件
Hibernate中主要涉及两个配置文件:主配置文件和映射文件。这两个配置文件的约束文件在Hibernate核心Jar文件 hibernate-core-5.0.1.Final.jar中的or.hibernate包中:
配置映射文件,即配置两个关系:实体类与数据库中表的映射关系,属性与表中字段的映射关系。
在Student类所在的包中定义和配置student.hbm.xml文件:
/p>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
2.3 配置主配置文件
2.3.1 配置DB连接四要素与方言
主配置文件中的数据库连接相关属性值可以在hibernate框架解压目录下的project/etc/hibernate.properties文件中找到。
DB连接四要素与方言的key:
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/test
root
02000059
org.hibernate.dialect.MySQL5Dialect
2.3.2 配置数据源
数据源的key:
org.hibernate.c3p0.internal.C3P0ConnectionProvider
注意:若不指定第三方数据源,将使用Hibernate内置的数据源
2.3.3 配置当前Session上下文
指定当前Session上下文为线程,即在同一线程内所使用的Session为同一Session。
thread
2.3.4 配置自动建表
update
2.3.5 配置控制台SQL输出
true
true
2.3.6 注册映射文件
2.3.7 主配置文件整体配置情况
/p>
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/test
root
02000059
org.hibernate.dialect.MySQL5Dialect
org.hibernate.c3p0.internal.C3P0ConnectionProvider
thread
update
true
true
2.4 创建数据库
使用Mysql自带的test数据库。
2.5 定义测试类
package com.eason.hibernate.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.eason.hibernate.po.Student;
public class Test {
public static void main(String[] args) {
//1.加载主配置文件和映射文件
Configuration configure = new Configuration().configure();
//2.创建session工厂对象
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.开启Session对象
Session session = sessionFactory.getCurrentSession();
try {
//4.开启事务
session.beginTransaction();
Student student = new Student("张三", 23, 93.5);
//5.执行操作
session.save(student);
//6.提交事务
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//7.回滚事务
session.getTransaction().rollback();
}
}
}
3 CRUD操作
3.1 工具类的创建
每次在获取Session时,都需要通过Configuration对象加载主配置文件和映射文件,并且要创建SessionFactory对象,降低了开发和执行效率。所以,对于Session对象的获取,可以创建一个工具类。
在primary项目中,创建一个utils顶层功能包,将工具类放入其中。
package com.eason.hibernate.hbnUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HbnUtils {
private static SessionFactory sessionFactory;
public static Session getSession() {
return getSessionFactory().getCurrentSession();
}
private static SessionFactory getSessionFactory() {
if(sessionFactory == null || sessionFactory.isClosed()) {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
return sessionFactory;
}
}
3.2 CURD测试
在primary项目的基础上,再创建一个测试类MyTest。在其中通过使用工具类HbnUtils来测试增、删、改和简单查询操作。
3.2.1 save()
//测试save()
@org.junit.Test
public void testSave() {
Student student = new Student("李四", 24, 94.5);
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
session.save(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.3.2 persist()
save()为Hibernate的API,而persist()为JPA的API。均用于完成持久化。
//测试persist()
@org.junit.Test
public void testPersist() {
Student student = new Student("李四", 24, 94.5);
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
session.persist(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2.3 delete()
其底层是根据id进行删除的。所以,指定的删除对象必须要有id属性。
//测试delete()
@org.junit.Test
public void testDelete() {
Student student = new Student();
student.setId(1);
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
session.delete(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2.4 update()
其底层是根据id进行修改的。所以,指定的修改对象必须要有id属性。
//测试update()
@org.junit.Test
public void testUpdate() {
Student student = new Student("赵六", 25, 95.5);
student.setId(2);
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
session.update(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2 5 saveOrUpdate()
通过参数对象是否具有id值来判断是执行save()操作还是执行update()操作。若参数对象具有id,但是该id在DB中不存在,则会抛出异常。
//测试saveOrUpdate()
@org.junit.Test
public void testSaveOrUpdate() {
// 设置要插入或者修改为的值
Student student = new Student("赵六", 28, 95.5);
//设置要修改的对象的id。该语句决定是执行save还是update()
student.setId(2);
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
session.saveOrUpdate(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2.6 get()
在查询无果时,会给出null,但是不会抛出异常。
//测试get()
@org.junit.Test
public void testGet() {
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
//没有id为90的student,其查询结果为null,没有异常抛出
Student student = session.get(Student.class, 90);
System.out.println(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2.7 load()
在查询无果时,会抛出异常。
//测//测试load()
@org.junit.Test
public void testLoad() {
Session session = HbnUtils.getSession();
try {
session.beginTransaction();
Student student = session.load(Student.class, 90);
//没有id为90的student,抛出异常
System.out.println(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
3.2.8 对于增、删、改的底层SQL执行顺序
对于不同操作对象的增、删、改操作,无论其代码的书写顺序是怎么样的,底层SQL的执行顺序都是insert、update、delete。
若要修改其底层的执行顺序,则可通过Session的flush()方法刷新Session完成。flush()会使得前后分隔为两部分,各部分会按照其顺序依次执行。
4 详解API
4.1 Configuration 接口
org.hibernate.cfg.Configuration接口的作用是加载主配置文件以及映射文件,以实现对Hibernate的启动。
Configuration 实例的获取方式:Configuration cfg = new Configuration().configure();。
4.1.1 new Configuration()
new Configuration()会加载一个属性文件hibernate.properties。该属性文件中存放着数据连接配置、Hibernate配置等配置信息。一般情况下不用设置该属性文件,其设置已经放在主配置文件中。若要设置,应将其放于src目录中。该文件的模版存放于Hibernate框架解压目录下的project/etc中。
4.1.2 无参configure()方法
configure()方法,默认用于加载和解析名称为hibernate.cfg.xml配置文件,并通过主配置文件找到并解析映射文件。该方法返回一个Configuration对象。所以,cfg是一个包含配置信息以及映射信息的Configuration对象。
在查看configure()方法的源码:
4.1.3 带参configure()方法
Hibernate主配置文件默认名称为hibernate.cfg.xml,应存放在src类路径下。但也可以更换路径和文件名。此时,需要使用带参的configure()方法。
4.2 SessionFactory接口
org.hibernate.SessionFactory接口对象是由Configuration对象通过buildSessionFactory()方法创建的。创建该对象的目的是,用于开启Session对象。
SessionFactory sessionFactory = cfg.buildSessionFactory();。
4.2.1 SessionFactory对象特点
重量级对象(系统开销大)、单例的、线程安全的。
按理说,单例对象一定是被共享的,是线程不安全的。但是查看SessionFactory接口的实现类SessionFactoryImpl源码,可以看起大多数成员变量时final的,所以是线程安全的。
4.2.2 SessionFactory对象的使用原则
基于其是线程安全的重量级对象,其创建和销毁时系统开销大,又是单例的特点,SessionFactory对象一般不手工关闭,而是在应用结束时自动将其销毁。因此,SessionFactory不用进行close()关闭。
4.3 Session接口
org.hibernate.classic.Session接口是应用程序与Hibernate连接的核心API,是Hibernate向应用程序提供的操纵DB的最主要的接口。它提供了基本的保存、更新、删除和查询方法。由SessionFactory对象创建。
Session s= sessionFactory.getCurrentSession();。
4.3.1 Session对象的特点
一个轻量级对象、线程不安全的、多例的。
在Web应用中,多个用户对同一应用访问,Hibernate会为每个用户创建一个Session对象。所以是多例的。Session中包含大量非final成员变量,对于同一个用户的操作,可能会产生多个事务。这多个事务若同时对同一个Session的同一个成员变量进行访问,就会引起并发问题。所以session是线程不安全的。
4.3.2 Session对象的使用原则
基于Session的以上特点,Session在使用时要做到一个线程一个Session,即一个事务一个Session。使用完毕,立即关闭。Session不要作为某个类的成员变量出现,因为这样会出现多个实例对象对同一个session的共享,使其不安全。
4.3.3 Session对象的获取
SessionFactory对于Session对象的获取,提供了两种获取方式:
sessionFactory.openSession():创建一个新的 Session 对象。
sessionFactory.getCurrentSession():获取当前线程中的 Session 对象。
1、openSession()方式:每次执行一次openSession()方法,均会创建一个新的Session对象。
2、getCurrentSession()方式:每次获取到的都是当前线程中的Session对象,都是同一个Session。
3、当前Session上下文:为了保证一个线程一个Session,即一个线程中使用的Session是同一个对象,一般在获取Session对象时,使用SessionFactory的getCurrentSession()方法。不过,使用该方法获取Session对象,需要在主配置文件中对Session所处的上下文环境,即事务环境进行注册。
hibernate.current_session_context_class取值有三种: