10分钟解决Hibernate的事务管理,Hibernate当中要设置事务的隔离级别

一、事务

1、什么是事务:

事务:事物指的是逻辑上的一组操作,组成这一组操作的逻辑单元要么全成功,要么全失败

2、事务的特性:

(1)原子性:代表事务不可分割。
(2)一致性:代表事务执行的前后,数据的完整性要保证一直。
(3)隔离性:代表的是一个事务执行的过程当中,不应该受到其他事务的干扰。
(4)持久性:代表一个事务执行完成后数据就持久到数据库当中(提交或回滚)。

3、如果我们不考虑事务的隔离性,就会引发一些安全性的问题

(一)读的问题
(1)脏读:一个事务读到另外一个事务未提交的数据
(2)不可重复读:一个事务读到了另一个事务已经提交的update的数据,导致在前一个事务多次查询结果不一致
(3)虚度/幻读:一个事务读到另外一个事务已经提交的但是insert的数据,导致在前一个事务当中多次查询的结果不一致
(二)写的问题
(1)引发两类丢失更新

4、读问题的解决

(一)设置事务的隔离级别
1、Read uncommitted:未提交读–以上的读问题都会发生
2、Read commited:解决脏读,但是不可重复读和虚读有可能发生(Oracle默认隔离级别)
3、Repeatable read:解决脏读和不可重复读,但是虚读是有可能发生的(MySQL默认隔离级别)

4、Serializable:解决所有的读问题(不能有事物的并发)(安全性高效率低)

二、Hibernate当中要设置事务的隔离级别

在这里插入图片描述
核心配置文件hibernate.cfg.xml当中配置对应的属性
4是mysql的默认隔离级别
8是Oracle的默认隔离级别
在这里插入图片描述

三、Service层事务

1、Hibernate如何解决Service的事务管理

在这里插入图片描述

2、使用getCurrentSession获取当前线程的session对象

(1)改写工具类

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/* Hibernate的工具类*/
public class HibernateUtils {
	public static final Configuration cfg;
	public static final SessionFactory sf;
	static {
		cfg = new Configuration().configure();
		sf = cfg.buildSessionFactory();
	}
	public static Session openSession() {
		return sf.openSession();
	}
	public static Session getCurrentSession() {
		return sf.getCurrentSession();
	}
}
<!-- 设置事务隔离级别 -->
<property name="hibernate.connection.isolaction">4</property> 

(2)配置完成(hibernate的核心配置文件当中)
在这里插入图片描述

<!-- 配置当前线程来绑定的session -->
<property name="hibernate.current_session_context_class">thread</property>

getCurrentSession获取当前线程的session对象,创建session对象之后不需要调用close方法,在线程结束的时候会自动将session关闭
(3)测试类

package com.itzheng.hibernate.demo01;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itzheng.hibernate.utils.HibernateUtils;
/*
 * 测试当前线程绑定的Session
 */
public class HibernateDemo04 {
	@Test
	public void demo01() {
		//会按照配置的好的事务处理方式去存储数据
		Session session = HibernateUtils.getCurrentSession();//保证每一个对象在调用该方法的时候都使用的是同一个session
		Transaction transaction = session.beginTransaction();
		Customer customer = new Customer();
		customer.setCust_name("王西");
		session.save(customer);
		transaction.commit();
		//session.close();不需要二次关闭session。因为在当前线程结束的时候就会关闭session对象,也就缓存
	}
}

在这里插入图片描述

Hibernate其他API(解决事务当中的问题)

以下API在运行的时候需要配置好核心文件当中

<?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>
	<!-- 链接数据库的基本参数 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day02</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<!-- 配置hibernate的方言的   目的是生成对应不同数据的语句 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>	
		<!-- 可选配置 -->
		<!-- 打印SQL -->
		<property name="hibernate.show_sql">true</property>
		<!-- 格式化sql -->
		<property name="hibernate.format_sql">true</property>
		<!-- 自动创建表 -->
		<property name="hibernate.hbm2ddl.auto">update</property>	
		
		
		<!-- 配置C3P0连接池 -->
		<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		<!--在连接池中可用的数据库连接的最少数目 -->
		<property name="c3p0.min_size">5</property>
		<!--在连接池中所有数据库连接的最大数目  -->
		<property name="c3p0.max_size">20</property>
		<!--设定数据库连接的过期时间,以秒为单位,
		如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
		<property name="c3p0.timeout">120</property>
		 <!--3000秒检查所有连接池中的空闲连接 以秒为单位-->
		<property name="c3p0.idle_test_period">3000</property>
		
		
		<!-- 设置事务隔离级别 -->
		<property name="hibernate.connection.isolaction">4</property> 
		
		<!-- 配置当前线程来绑定的session -->
		<property name="hibernate.current_session_context_class">thread</property> 
		
		
		<mapping resource="com/itzheng/hibernate/demo01/Customer.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

以及准备好对应的工具类

public class HibernateUtils {
	public static final Configuration cfg;
	public static final SessionFactory sf;
	static {
		cfg = new Configuration().configure();
		sf = cfg.buildSessionFactory();
	}
	public static Session openSession() {
		return sf.openSession();
	}
	public static Session getCurrentSession() {
		return sf.getCurrentSession();
	}
}

一、Query

Query接口用于接收HQL,查询多个对象。
HQL:Hibernate Query Language :Hibernate查询语言。这种语言与SQL的语法及其类似,是一个面向对象的查询语言。

1、查询所有表当中信息

public class HibernateDemo5 {
	@Test
	// Query
	public void demo01() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session活动Query接口
		String hql = "from Customer";
		Query query = session.createQuery(hql);
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}
}

在这里插入图片描述
2、查询指定字符的数据(条件查询)

/*
 * Hibernate的其他的API
 */
public class HibernateDemo5 {
	@Test
	// Query
	public void demo01() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session活动Query接口
		// String hql = "from Customer";
		String hql = "from Customer where cust_name like ?";
		Query query = session.createQuery(hql);
		query.setParameter(0, "王%");
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}
}

在这里插入图片描述
分页查询

/*
 * Hibernate的其他的API
 */
public class HibernateDemo5 {
	@Test
	// Query
	public void demo01() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session活动Query接口
		//分页查询
		String hql = "from Customer";
		Query query = session.createQuery(hql);
		//设置分页
		query.setFirstResult(0);//相当于MySQL当中limit的第一个参数
		query.setMaxResults(3);
		//query.setParameter(0, "王%");
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}
}

在这里插入图片描述
改变初始值

	@Test
	// Query
	public void demo01() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session活动Query接口
		//分页查询
		String hql = "from Customer";
		Query query = session.createQuery(hql);
		//设置分页---》会根据不同的数据库切换SQL语句
		query.setFirstResult(3);//相当于MySQL当中limit的第一个参数
		query.setMaxResults(3);
		//query.setParameter(0, "王%");
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

在这里插入图片描述

二、Criteria

Criteria:QBC(Query By Criteria);
更加面向对象的一种查询方式。

@Test
	// Criteria
	public void demo02() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session获得Criteria接口
		Criteria criteria = session.createCriteria(Customer.class);// 返回
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

在这里插入图片描述
条件查询

@Test
	// Criteria
	public void demo02() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session获得Criteria接口
		Criteria criteria = session.createCriteria(Customer.class);//先获取到criteria的Customer对象
		//criteria.add(Restrictions.like("cust_name", "王%"));//设置对应的查询的条件
		criteria.add(Restrictions.like("cust_name", "王",MatchMode.START));//在这里上下这两种设置条件的方式实现的功能一致
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

分页查询

@Test
	// Criteria
	public void demo02() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session获得Criteria接口
		/*
		 * Criteria criteria = session.createCriteria(Customer.class);// 返回
		 * List<Customer> list = criteria.list();
		 */
		Criteria criteria = session.createCriteria(Customer.class);//先获取到criteria的Customer对象
		//criteria.add(Restrictions.like("cust_name", "王%"));//设置对应的查询的条件
		criteria.add(Restrictions.like("cust_name", "王",MatchMode.START));//在这里上下这两种设置条件的方式实现的功能一致
		criteria.setFirstResult(0);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

在这里插入图片描述
修改初始值

@Test
	// Criteria
	public void demo02() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 通过Session获得Criteria接口
		/*
		 * Criteria criteria = session.createCriteria(Customer.class);// 返回
		 * List<Customer> list = criteria.list();
		 */
		Criteria criteria = session.createCriteria(Customer.class);//先获取到criteria的Customer对象
		//criteria.add(Restrictions.like("cust_name", "王%"));//设置对应的查询的条件
		criteria.add(Restrictions.like("cust_name", "王",MatchMode.START));//在这里上下这两种设置条件的方式实现的功能一致
		criteria.setFirstResult(3);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

在这里插入图片描述

三、SQLQuery

SQLQuery用于接收一个SQL语句。如果是特别复杂的使用SQL

@Test
	// createSQLQuery
	public void demo03() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		
		
		SQLQuery query = session.createSQLQuery("select * from cst_customer");
		query.addEntity(Customer.class);//设置查询返回时返回对象的元素
		List<Customer> list = query.list();
		for (Customer customer : list) {
			
			System.out.println(customer);
			
		}
		transaction.commit();
	}

在这里插入图片描述

原创文章 76 获赞 151 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_44757034/article/details/105752807