原先的连接Connection,只能是来一次,新创建一个连接connection。这样如果事务在Dao层已经默认提交,在service层出错时,对于俩张关联会有俩种不同的结果。为了解决这样的问题,我们将事务提升到service层。用到  threadlocation。

package com.bjsxt.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; public class DBUtil2 {
static String driver;
static String url;
static String user;
static String password;
//定义一个threadLocal变量,存放collection,可以保证在同于个线程中,多个不同层次,不同方法,都是用的是同一个collection。
private static ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();
//读取属性文件properties并获取内容
static{
//准备一个空的map,没有key-value
Properties prop = new Properties(); //读取文件,并将文件键值对存入Properties对象
//InputStream is = new FileInputStream(new File("C:\Users\Administrator\workspace\java_empmgr2\src\conn.properties"));
InputStream is = DBUtil2.class.getResourceAsStream("/jdbc.properties"); //classpath
try {
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//从prop中根据key获取四个参数的值
driver = prop.getProperty("driver");
//driver = prop.get("driver");
url = prop.getProperty("url");
user = prop.getProperty("username");
password = prop.getProperty("password"); //加载驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} /**
* 获取数据库连接
* @return
*/
public static Connection getConnection(){
Connection conn = null;
//不是直接创建新的连接,而是次用threadLocal中获取
conn = threadLocal.get();
if (conn==null) {
//当前线程第一次获取连接,需要建立数据库的连接
try{
//建立数据库连接
conn = DriverManager.getConnection(url, user, password);
}catch(SQLException e){
e.printStackTrace();
}
//再放入threadlocal
threadLocal.set(conn);
} return conn; } /**
* 关闭数据库资源
* @param rs
* @param stmt
* @param conn
*/
public static void closeAll(ResultSet rs ,Statement stmt,Connection conn){
//关闭数据库资源
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
} try {
if(stmt != null){
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
} try {
if(conn != null){
threadLocal.set(null);//将conn从threadLocal中移除
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
} /**
* DML:insert update delete
*/
public static int executeUpdate(String sql,Object ... params) {
Connection conn = null;
PreparedStatement pstmt = null;
int n = 0;
try{
//获取数据库连接
conn = DBUtil2.getConnection(); //使用手枪发送SQL命令并得到结果
pstmt = conn.prepareStatement(sql); for(int i=0;i<params.length;i++){
pstmt.setObject(i+1, params[i]);
}
n = pstmt.executeUpdate(); }catch(SQLException e){
//处理异常
e.printStackTrace();
//throw e;
//抛出异常给上级(调用者)
//throw new RuntimeException(e.toString());
throw new MyException(e.toString());
}finally{
//关闭数据库资源
DBUtil2.closeAll(null, pstmt, null);//采用业务层事务后,dao层不关闭连接
} //返回数据
return n;
}
public static void main(String[] args) {
Connection conn = getConnection();
System.out.println(conn);
}
}

比原先的工具类不同的是。用到 DBUtil2时,我们将关闭connection都放在service层统一关闭。

public void add(Expense expense) {
//获取序列的下一个值,
ExpenseDao expDao = new ExpenseDaoImpl();
int expId = expDao.nextVal();
//开启手动提交事务
Connection conn=DBUtil2.getConnection();
try {
//将自动提交事务关闭(此时并没有事务提交)
conn.setAutoCommit(false); //添加一条报销单(主单)信息
expense.setExpId(expId);
expDao.save(expense); //添加多条报销单所属的明细的信息
ExpenseItemDao itemDao = new ExpenseItemDaoImpl();
List<ExpenseItem> itemList = expense.getItemList();
for(int i=0;i<itemList.size();i++){
ExpenseItem item = itemList.get(i);
item.setExpId(expId);
itemDao.save(item);
}
//结束事务(提交或者回滚)
conn.commit();//提交事务
} catch (Exception e) {
try {
//回滚事务
conn.rollback();//会清空缓存
} catch (SQLException e1) {
e1.printStackTrace();
throw new MyException(e1.toString());
}
throw new MyException(e.toString());
}
finally{
DBUtil2.closeAll(null, null, conn);
}
}

对于在Dao层,一个DML操作一个事务,升级到Service层,一个用户,一个事务的更多相关文章

  1. spring事务到底用于service层还是dao层

    Spring事务为业务逻辑进行事务管理,保证业务逻辑上数据的原子性. 事务得根据项目性质来细分:事务可以设置到三个层面(dao层.service层和web层). 第一:web层事务,这一般是针对那些安 ...

  2. MVC引入SERVICE层 提高代码重用性 沟通CONTROL和MODEL

    MVC是web开发中常见的程序结构. 简单的mvc结构如下: view层:显示层. control层:业务层,集合了各种action. model层:模型层,一般和数据打交道.简单的sample:一个 ...

  3. 032医疗项目-模块三:药品供应商目录模块——供货商药品目录查询功能----------Service层和Action层和调试

    我们上一篇文章讲了Dao层代码: 这一篇我们讲解Service层和Action层: Service层: 分为接口和实现类,我们主要看实现类:GysemplServiceImpl package yyc ...

  4. SSM实战——秒杀系统之Service层接口设计与实现、Spring托管、声明式事务

    一:Service层接口设计 准备工作:新建三个包:service包.exception包.dto包,分别用来存放业务接口.自定义异常类.dto类. 1:定义接口 package org.myseck ...

  5. 【spring data jpa】使用spring data jpa时,关于service层一个方法中进行【删除】和【插入】两种操作在同一个事务内处理

    场景: 现在有这么一个情况,就是在service中提供的一个方法是先将符合条件的数据全部删除,然后再将新的条件全部插入数据库中 这个场景需要保证service中执行两步 1.删除 2.插入 这两步自然 ...

  6. 【mybatis】service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据【事务的问题】

    问题描述: service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据 ...

  7. iBatis——自动生成DAO层接口提供操作函数(详解)

    iBatis——自动生成DAO层接口提供操作函数(详解) 在使用iBatis进行持久层管理时,发现在使用DAO层的updateByPrimaryKey.updateByPrimaryKeySelect ...

  8. UDP 一个封锁操作被对 WSACancelBlockingCall 的调用中断

    using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using S ...

  9. [Socket网络编程]一个封锁操作被对 WSACancelBlockingCall 的调用中断。

    原文地址:http://www.cnblogs.com/xiwang/archive/2012/10/25/2740114.html记录在此,方便查阅. C#中在使用UDPClient循环监听端口,在 ...

随机推荐

  1. 网站搭建-虚拟机的使用-Linux (包括输入法和QQ下载使用)

    之前已经联网了,基本的软件系统会自己下载,先不用管. 1. 先下载一个中文输入法吧: 先改一下Firefox的搜索引擎吧,因为大陆不支持google 下载,安装,就完事了,还好这个没变,几年不用这个系 ...

  2. [javascript] 编写一个计算器,实现加减法

    1.代码 <script> function sum(){ //加法 var value1 = document.getElementById("num1").valu ...

  3. [深度学习][图像处理][毕设][笔记][安装环境][下载地址]安装VS2013、matconvnet、cuda、cudnn过程中产生的一些记录,2018.5.6号

    最近半个多月,被cuda等软件折磨的死去活来,昨天下午,终于安装好了环境,趁着matlab正在,在线下载VOT2016数据集,3点睡眼惺忪被闹醒后,睡不着,爬上来写这份记录. 先记录一下自己电脑的基本 ...

  4. B2B市场新的营销思路

    随着互联网+时代的到来,企业与企业之间的联系已经慢慢从传统的服务模式转变为网上服务,企业与企业之间通过网络,进行数据信息的交换.传递,开展交易活动的商业模式我们称之为B2B B2B使企业大大节约了企业 ...

  5. [ERROR]Unable to locate package

    刚更换了DNS,需要更新下apt-get $ apt-get update

  6. dubbo分布式Service不可以创建Error creating bean with name 'XXXXXX'

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoService' ...

  7. nyoj 260-数数小木块 (打表)

    260-数数小木块 内存限制:64MB 时间限制:3000ms 特判: No 通过数:17 提交数:24 难度:1 题目描述: 在墙角堆放着一堆完全相同的正方体小木块,如下图所示: 因为木块堆得实在是 ...

  8. 如何评价 Vue 的 Function-based Component?

    作者:匿名用户链接:https://www.zhihu.com/question/325397290/answer/708418099来源:知乎 事实性错误: 那 vue 呢?它连 HOC 都没有,r ...

  9. list,tuple,dict,set 思维导图整理

  10. Leetcode 25/24 - Reverse Nodes in k-Group

    题目描述 Leetcode 24 题主要考察的链表的反转,而 25 题是 24 的拓展版,加上对递归的考察. 对题目做一下概述: 提供一个链表,给定一个正整数 k, 每 k 个节点一组进行翻转,最后返 ...