Hibernate中事务小案例
理论知识:
什么是事务?
指作为单个逻辑工作单位执行的一系列操作,要么完全的执行,要么完全不执行。事务处理可以确保非事务性单元内的所有操作都完全完成,否则永久不会更新面向数据的资源。通过将一组操作组合为一个要么成功要么失败的单元,可以简化错误恢复并使应用程序更加可靠。
事务并发的问题:
(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中事务小案例的更多相关文章
- JavaWeb_(Hibernate框架)Hibernate中事务
Hibernate中事务 事务的性质 事物的隔离级别 配置事务的隔离级别 事务的性质 原子性:原子,不可再分,一个操作不能分为更小的操作,要么全都执行,要么全不执行. 一致性:事务在完成时,必须使得所 ...
- Hibernate中事务的隔离级别设置
Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下
- Hibernate中事务声明
Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...
- 关于Unity中的小案例之运动的小船以及摄像机跟随技术(专题五)
实例步骤 1.创建Unity项目和文件目录,保存场景 场景搭建 2.导入美术做好的资源包(第68) a: 导入地形资源包terrain.unitypackage,把里面的Map/Prefabs/Ter ...
- js中的小案例(一)
效果图: html代码: <div id="date"> <p> <span id="prev">上一月</span& ...
- 七、hibernate的事务使用
hibernate中事务隔离级别 1:读未提交 2:读已提交 4:可重复读 8:可串行化 hibernate事务使用 在核心配置文件中配置事务隔离级别 <property name=" ...
- Hibernate中的配置对象
数据库连接:由 Hibernate 支持的一个或多个配置文件处理.这些文件是 hibernate.properties 和 hibernate.cfg.xml. 类映射设置:这个组件创造了 Java ...
- Hibernate的介绍及入门小案例
1.Hibernate的诞生 在以前使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是对于大型应用系统的开发,使用JDBC就会显得力不从心,例如对几十,几百张包含几十个字段 ...
- (八) Hibernate中的Session以及事务
HibernateUtil.getSessionFactory().getCurrentSession() 和HibernateUtil.getSession() 的区别: 1.异:getCurren ...
随机推荐
- oracle 字符串截取substr和instr
SUBSTR(string,start_position,[length]) 求子字符串,返回字符串解释:string 元字符串 start_position 开始位置(从0开始 ...
- WPF中的Command事件绑定
在项目中使用Command绑定能够使我们的代码更加的符合MVVM模式.不了解的同学可能不清楚,只有继承自ButtonBase类的元素才可以直接绑定Command(Button.CheckBox.Rad ...
- Hadoop2.7.3+Spark2.1.0 完全分布式环境 搭建全过程
一.修改hosts文件 在主节点,就是第一台主机的命令行下; vim /etc/hosts 我的是三台云主机: 在原文件的基础上加上; ip1 master worker0 namenode ip2 ...
- win7连接共享打印机
1. 保证目标电脑启用共享.打印机驱动安装正常 2. 目标电脑进入"设备和打印机" 3. 右键要共享的打印机 - 打印机属性 -共享此打印机 4. 其他电脑打印时,选择其他打印机, ...
- ubuntu17.10 安装firefox的flash
1. flash下载地址:https://get.adobe.com/flashplayer/ 2. 选择tar.gz for linux 3. 下载后解压tar包.里面有个libflashplaye ...
- 03 JVM的垃圾回收机制
1.前言 理解JVM的垃圾回收机制(简称GC)有什么好处呢?作为一名软件开发者,满足自己的好奇心将是一个很好的理由,不过更重要的是,理解GC工作机制可以帮助你写出更好的Java程序. 在学习GC前,你 ...
- 第十八章 DjangoWeb开发框架
第十八章 DjangoWeb开发框架 第一课 内容概要: 1.JS正则 -登录注册验证 2.组件 1.BootStrap -css -js 学习BootStrap规则 2.jQueryUI -css ...
- RotatedRect 类的用法
RotatedRect 以 Emgu.CV.Structure 为命名空间. 表示带有旋转角度的矩形. 结构说明 普通矩形的基本结构
- MyCat 读写分离,负载均衡
docker mysql 主从复制 配合Spring 事务 注意事项 配置好JRE,安装好MYCAT 在mysql主库创建表,会同步到从库 CREATE TABLE `user` ( `id` ) N ...
- Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置
该篇为Sping Boot入门到实战系列入门篇的第四篇.介绍Spring Boot自动化配置的基本原理与实现. Spring Boot之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...