理论知识:

什么是事务?

指作为单个逻辑工作单位执行的一系列操作,要么完全的执行,要么完全不执行。事务处理可以确保非事务性单元内的所有操作都完全完成,否则永久不会更新面向数据的资源。通过将一组操作组合为一个要么成功要么失败的单元,可以简化错误恢复并使应用程序更加可靠。

并发控制概述
事务是并发控制的基本单位,保证事务ACID的特性是事务处理的重要任务,而并发操作有可能会破坏其ACID特性。
DBMS并发控制机制的责任:
对并发操作进行正确调度,保证事务的隔离性更一般,确保数据库的一致性。

事务并发的问题:

(1)脏读:读到另一个事务未提交前的数据。

(2)不可重复读:同一条记录2次读取到的数据不一样。

(3)幻读(虚读):同一个表,2次查询到的数据不一样。

事务的隔离级别:

(1)读,未提交(read uncommited):什么都没解决,性能最好,一般不用。

(2)读已提交数据(read commited):Oracle默认,解决了脏读。

(3)可重复读(repeatable read):Mysql默认,解决了脏读,不可重复读。

(4)串行化(serializable序列化),容易产生死锁。解决所有上述并发问题。

#查询事务隔离级别
SELECT @@tx_isolation;
#修改隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL read UNCOMMITTED ;

 

案例演示:

A向B转账,A金额减少,B金额增加。 若转账中出现问题,则A和B的金额都不变。

public class User {

    private Integer uid;
// private String uid;
private String name;
private String password;
private Double balance; //金额 public Integer getUid() {
return uid;
} public void setUid(Integer uid) {
this.uid = uid;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public Double getBalance() {
return balance;
} public void setBalance(Double balance) {
this.balance = balance;
} @Override
public String toString() {
return "User{" + "uid=" + uid + ", name='" + name + '\'' + ", password='" + password + '\'' + ", balance=" + balance + '}';
}
}

实体类

 <!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
name:User的相对路径
table:数据库表的名称
-->
<class name="a_helloworld.entity.User" table="t_user">
<!--
一个类标签里面必须有一个id.
hibernate要求实体类有一个属性是唯一值。
column:数据库列名 可以省略,省略的话默认和name的值一样
-->
<id name="uid" column="uid">
<!--
主键的生成策略
native:主键自动增长
uuid:自动生成一个长度为32的字符串
-->
<generator class="native"></generator>
</id>
<!--
其他普通属性
type:一般不去设置 框架会自动对应
not-null:非空
-->
<property name="name"></property>
<property name="password"></property>
<property name="balance"></property>
</class>
</hibernate-mapping>

实体类映射文件

 <!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>
<!--1 数据库信息-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate001?characterEncording=UTF-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property> <!--2 配置hibernate信息 可选部分-->
<!--在控制台输出底层sql语句
项目在开发阶段设置为true 项目发布的时候改成false
因为日志信息会写在文件中(io操作),浪费额外的资源
-->
<property name="show_sql">true</property>
<!--对输出的sql语句进行格式化-->
<property name="format_sql">true</property> <!--hibernate帮助我们创建表的策略需要配置
create:每次执行都重新创建表,数据会丢失
update:如果已经有表,更新。如果没有就创建(一般使用)
create-drop:每次执行都重新创建,数据丢失(开发的时候使用)
validate:校验。每次运行校验数据库表是否正确(不会更新或创建表)
-->
<property name="hbm2ddl.auto">update</property> <!--配置数据库方言
告诉hibernate你用的是什么方言
Mysql:limit
oracle:rownum
让hibernate识别不同数据库的自己特有的语句
-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!--设置事务隔离级别-->
<property name="hibernate.connection.isolation">4</property> <!--当前session绑定本地线程-->
<property name="hibernate.current_session_context_class">thread</property> <!--3 把映射文件加载-->
<mapping resource="b_Query/entity/User.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>

hibernate核心配置文件

public interface UserService {
public void transfer(Integer from,Integer to,Double money);
}

service层接口

 public class UserServiceImpl implements UserService {
private UserDAO userDAO = new UserDAOImpl();
@Override
public void transfer(Integer from, Integer to, Double money) { Session session = HibernateUtils.getCurrentSession(); /* //验证 session是否相同
Session session1 = HibernateUtils.getCurrentSession();
System.out.println(session == session1);*/ Transaction transaction = session.beginTransaction(); try {
//from 减少金额
userDAO.reduce(from,money); int i =5/0;
//to 增加金额
userDAO.increase(to,money);
transaction.commit();
}catch (Exception e){
e.printStackTrace();
transaction.rollback();
} }
}

service层接口实现

public interface UserDAO {
public void increase(Integer id,Double money);
public void reduce(Integer id,Double money);
}

DAO层接口

public class UserDAOImpl implements UserDAO {
@Override
public void increase(Integer id, Double money) {
Session session = HibernateUtils.getCurrentSession(); User user = session.get(User.class, id);
user.setBalance(user.getBalance()+money);
session.update(user); } @Override
public void reduce(Integer id, Double money) {
Session session = HibernateUtils.getCurrentSession(); User user = session.get(User.class, id);
user.setBalance(user.getBalance()-money);
session.update(user); }
}

DAO层接口实现

public class HibernateUtils {
private static Configuration configure;
private static SessionFactory sessionFactory;
static {
configure = new Configuration().configure();
sessionFactory = configure.buildSessionFactory();
} public static SessionFactory getsessionFactory(){
return sessionFactory;
} //获取session
public static Session getSession(){
return sessionFactory.openSession();
} //拿到和当前线程绑定的session
public static Session getCurrentSession(){
Session currentSession = sessionFactory.getCurrentSession();
return currentSession;
}
}

hibernate工具类

public class BalanceDemo {
@Test
public void transfer(){
UserService userService = new UserServiceImpl();
userService.transfer(2,1,5.0);
}
}

测试类

在业务层如果转账过程中出现了问题,事务回滚,可以保证数据库的一致性。

转账前的记录:

处理业务时产生异常:

这时后刷新记录发现记录中的balance字段(表示金额)数值不变。业务逻辑实现类中,转账后捕获到了异常事务进行了回滚。

若没有产生异常,则两条记录的金额都发生变化。

注意:

1.在hibernate.cfg.xml核心配置文件中可以配置事务隔离级别  4表示repeatable read

<property name="hibernate.connection.isolation">4</property>

2.在DAO层操作数据库需要用到session,在service层获取事务也需要session,我们要确保2个session为同一个对象

解决:将session与本地线程绑定。

需要在hibernate.cfg.xml核心配置文件中配置

<!--当前session绑定本地线程-->
<property name="hibernate.current_session_context_class">thread</property>

Hibernate中事务小案例的更多相关文章

  1. JavaWeb_(Hibernate框架)Hibernate中事务

    Hibernate中事务 事务的性质 事物的隔离级别 配置事务的隔离级别 事务的性质 原子性:原子,不可再分,一个操作不能分为更小的操作,要么全都执行,要么全不执行. 一致性:事务在完成时,必须使得所 ...

  2. Hibernate中事务的隔离级别设置

    Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下

  3. Hibernate中事务声明

    Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...

  4. 关于Unity中的小案例之运动的小船以及摄像机跟随技术(专题五)

    实例步骤 1.创建Unity项目和文件目录,保存场景 场景搭建 2.导入美术做好的资源包(第68) a: 导入地形资源包terrain.unitypackage,把里面的Map/Prefabs/Ter ...

  5. js中的小案例(一)

    效果图: html代码: <div id="date"> <p> <span id="prev">上一月</span& ...

  6. 七、hibernate的事务使用

    hibernate中事务隔离级别 1:读未提交 2:读已提交 4:可重复读 8:可串行化 hibernate事务使用 在核心配置文件中配置事务隔离级别 <property name=" ...

  7. Hibernate中的配置对象

    数据库连接:由 Hibernate 支持的一个或多个配置文件处理.这些文件是 hibernate.properties 和 hibernate.cfg.xml. 类映射设置:这个组件创造了 Java ...

  8. Hibernate的介绍及入门小案例

    1.Hibernate的诞生 在以前使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是对于大型应用系统的开发,使用JDBC就会显得力不从心,例如对几十,几百张包含几十个字段 ...

  9. (八) Hibernate中的Session以及事务

    HibernateUtil.getSessionFactory().getCurrentSession() 和HibernateUtil.getSession() 的区别: 1.异:getCurren ...

随机推荐

  1. Laravel (5.5.33) 加载过程---instance方法(二)

    在bootstrap/app.php /** * 对于其中的instance register singleton 方法到时候单独拎出来说明 * * 1.设置基础路径 * 2.使用instance 方 ...

  2. VS2008集成PC-lint

    引言 C/C++语言的语法拥有其它语言所没有的灵活性,这种灵活性带来了代码效率的提升,但相应也使得代码编写具有很大的随意性,另外C/C++编译器不进行强制类型检查,也不做任何边界检查,这就增加了代码中 ...

  3. 较复杂makefile跟lds脚本程序的编写

    首先看个makefile范例: /*指明工具链,并为其取个简单的别名*/ CC = arm-linux-gcc LD = arm-linux-ld AR = arm-linux-ar OBJCOPY ...

  4. window MySQL解压缩版部署及配置

    MySQL安装分为解压文件和直接安装.exe文件 我在官网下载的是解压文件 官网下载地址https://dev.mysql.com/downloads/mysql/ 一.MySQL部署 1.将下载下来 ...

  5. 高仿QQ Xplan的H5页面

    概述 这个h5的主要玩法很简单:地球自转的时候会播放背景音乐(比如海浪声),为了找到这个声音是从哪个地球上哪个地方传来的,需要长按下方的按钮,这时地球会自动转动到目标地点,然后镜头拉近,穿过云层,最后 ...

  6. Quartz.NET 3.0 正式发布

    Quartz.NET是一个强大.开源.轻量的作业调度框架,你能够用它来为执行一个作业而创建简单的或复杂的作业调度.它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等.在2017 ...

  7. 炸金花的JS实现从0开始之 -------现在什么都不会(1)

    新年结束了.回想起来唯一留下乐趣的就是在家和朋友玩玩炸金花. 遂有此文. 对不起,我这时候还没有思路. 让我捋一捋. ... ... 捋一捋啊... ... 好了.今天先这样吧: (1)先整理出所有的 ...

  8. canvas常用api

    1. 在canvas标签中给出长宽(不带单位):<canvas width="600" height="600"></canvas> 或 ...

  9. linux下双网卡的绑定

    如果服务器上有两快网卡就可以把它绑定为一块虚拟的网卡,如果一块网卡坏了另一块还可以继续工作,增加了冗余度和负载,具体做法如下: 新建一个虚拟的网卡,命令如下: iv /etc/sysconfig/ne ...

  10. Spring Boot : Whitelabel Error Page解决方案

    楼主最近爱上了一个新框架--Spring Boot, 搭建快还不用写一堆xml,最重要的是自带Tomcat 真是好 pom.xml <?xml version="1.0" e ...