hibernate mysql 多线程_SSH框架之Hibernate5专题2:Hibernate基本技术

举例: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包中:

43bcc5de313392c126d3f94d70adc76e.png

01b33600edfcbe6ebfc4f6ea4041e5f7.png

配置映射文件,即配置两个关系:实体类与数据库中表的映射关系,属性与表中字段的映射关系。

在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:

27028112c467eb8c71b3209a8b8b4126.png

com.mysql.jdbc.Driver

jdbc:mysql://localhost:3306/test

root

02000059

org.hibernate.dialect.MySQL5Dialect

2.3.2 配置数据源

数据源的key:

665c9306bbe01c3ba13facf55a4eee2d.png

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中。

63dc51feada3abaf661f94890b52558d.png

4.1.2 无参configure()方法

configure()方法,默认用于加载和解析名称为hibernate.cfg.xml配置文件,并通过主配置文件找到并解析映射文件。该方法返回一个Configuration对象。所以,cfg是一个包含配置信息以及映射信息的Configuration对象。

在查看configure()方法的源码:

37e6e130f1f816ec4bfad5a6d288f3f7.png

c7d6f22190d20ba41d0a20502276030b.png

4.1.3 带参configure()方法

Hibernate主配置文件默认名称为hibernate.cfg.xml,应存放在src类路径下。但也可以更换路径和文件名。此时,需要使用带参的configure()方法。

19135c540179f4bf332395ca6fc00133.png

f99629e6740c82be357d9e0f36aff295.png

4.2 SessionFactory接口

org.hibernate.SessionFactory接口对象是由Configuration对象通过buildSessionFactory()方法创建的。创建该对象的目的是,用于开启Session对象。

SessionFactory sessionFactory = cfg.buildSessionFactory();。

4.2.1 SessionFactory对象特点

重量级对象(系统开销大)、单例的、线程安全的。

按理说,单例对象一定是被共享的,是线程不安全的。但是查看SessionFactory接口的实现类SessionFactoryImpl源码,可以看起大多数成员变量时final的,所以是线程安全的。

c13bd7d3507849345229b0bc4b3c3300.png

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是线程不安全的。

4b7648fdde4f23e0fd1fa3b572f593c7.png

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对象。

d7273a42a4d11dc4aa79ab68aab916f0.png

2、getCurrentSession()方式:每次获取到的都是当前线程中的Session对象,都是同一个Session。

ce2a4883a17eb11aad71ef96abd9711a.png

3、当前Session上下文:为了保证一个线程一个Session,即一个线程中使用的Session是同一个对象,一般在获取Session对象时,使用SessionFactory的getCurrentSession()方法。不过,使用该方法获取Session对象,需要在主配置文件中对Session所处的上下文环境,即事务环境进行注册。

6bbc08486d0c888011292e34bbb0a311.png

hibernate.current_session_context_class取值有三种:


版权声明:本文为weixin_42107561原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。