连接池&Dbutils
一、连接池
1.1、连接池简述及原理
1.1.1、连接池简述及原理
DataSource 由连接池厂商去具体实现对应的连接池
使用连接池的目的:解决了数据库连接消耗资源和时间的很多问题,提高了性能和效率
常见的连接池有哪些?
DBCP连接池 C3P0连接池 Druid(阿里连接池)
经常用到的哪个公司的技术?
1、SUN公司(java 、 mysql) 后来被Oracle收购了
2、Oracle公司
3、Apache组织
4、阿里公司
DBCP连接池和C3P0连接池区别:
1、dbcp连接池使用效率高,但是安全性偏低
2、C3P0连接池效率偏低,但是安全性高
1.1.2、案例数据准备(步骤一)
SQL准备:
create table product(
pid int primary key,
pname varchar(20),
price double
);
INSERT INTO product(pid,pname,price) VALUES(1,'联想',5000);
INSERT INTO product(pid,pname,price) VALUES(2,'海尔',3000);
INSERT INTO product(pid,pname,price) VALUES(3,'雷神',5000);
INSERT INTO product(pid,pname,price) VALUES(4,'JACK JONES',800);
INSERT INTO product(pid,pname,price) VALUES(5,'真维斯',200);
INSERT INTO product(pid,pname,price) VALUES(6,'花花公子',440);
INSERT INTO product(pid,pname,price) VALUES(7,'劲霸',2000);
INSERT INTO product(pid,pname,price) VALUES(8,'香奈儿',800);
INSERT INTO product(pid,pname,price) VALUES(9,'相宜本草',200);
INSERT INTO product(pid,pname,price) VALUES(10,'面霸',5);
INSERT INTO product(pid,pname,price) VALUES(11,'好想你枣',56);
INSERT INTO product(pid,pname,price) VALUES(12,'香飘飘奶茶',1);
1.2、DBCP连接池
1.2.1、简述
DBCP也是一个开源的连接池,是Apache Common成员之一,在企业开发中也比较常见,tomcat内置的连接池。
DBCP连接池目前市面上极为高效的连接池。
DBCP连接池一秒钟可以创建并传递10万个左右的连接对象。
DBCP安全性并不高,有可能在高速运转丢失连接数据
1.2.2、连接池使用
1.2.1.1、导入jar包(步骤二)
1.2.1.2、配置文件导入(步骤三)
配置文件名称: (*.properties)
配置文件位置:可存放任意目录,但开发建议src根目录
需求:使用连接池查询商品的名字
案例实现:
package com.zql;
import com.sun.org.apache.bcel.internal.generic.LoadClass;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @Author:Daniel
* @Version 1.0
*/
public class DbcpTest {
/*使用连接池查询商品的名字*/
public static void main(String[] args) throws Exception {
//创建连接池对象
Properties pr = new Properties();
InputStream is = DbcpTest.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
pr.load(is);
DataSource ds = BasicDataSourceFactory.createDataSource(pr);
//获取连接
Connection conn = ds.getConnection();
String sql = "select * from product";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){
System.out.println(rs.getString("pname"));
}
}
}
运行显示为:
1.2.1.3、编写连接池工具
(1)案例结构:
(2)创建连接池:
package com.zql.utils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @Author:Daniel
* @Version 1.0
*/
public class DbcpUtils {
public static DataSource dataSource;
static {
//创建连接池
try {
Properties properties = new Properties();
InputStream inputStream = DbcpUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
properties.load(inputStream);
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
(3)修改测试代码:
1.2.1.4、常见配置项(参照dbcpconfig.properties)-附录
dbcpconfig.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dbutils
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
1.3、C3P0连接池
1.3.1、简述
C3P0属于开源的连接池,并且免费。目前使用它的开源框架有:Spring、Hibernate等
也属于第三方的插件,同样是不是需要导包(jar包)
1.3.2、连接池使用
1.3.2.1、导入jar包
1.3.2.2、配置文件引入
配置文件名称:c3p0-config.xml
配置文件位置:src
需求:使用连接池查询商品的名字
案例结构:
案例实现:
package com.zql.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class C3p0Test {
//需求:使用连接池查询商品的名字
public static void main(String[] args) throws Exception {
//创建连接池
//ComboPooledDataSource cps = new ComboPooledDataSource();//未命名
ComboPooledDataSource cps = new ComboPooledDataSource("zql");//命名 可到文件 c3p0-config.xml进行配置
//获取连接池
Connection connection = cps.getConnection();
String sql = "select * from product";
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("pname"));
}
}
}
1.3.2.3、编写连接池工具—默认配置
(1)
package com.zql.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class C3p0Utils {
//创建连接池
public static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//获取连接
public static Connection getConnection() throws SQLException {
return comboPooledDataSource.getConnection();
}
}
(2)修改测试代码:
1.3.2.4、编写连接池工具—命名配置(了解)
1.3.2.5、常见配置项-附录
二、DBUtils工具
2.1、DBUtils工具简述及导入
DBUtils是java编程中的数据库操作实用工具,小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能介绍
QueryRunner中提供对sql语句操作的API.(核心类 使用它调用增删改查的方法)
ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
(1)导入一系列jar包:
(2)创建C3P0Utils类
package com.zql.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class C3p0Utils {
//创建连接池
public static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource() {
return dataSource;
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
(4)创建Demo
package com.zql.utils;
import org.apache.commons.dbutils.QueryRunner;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Demo {
public static void main(String[] args) {
//手动模式
QueryRunner qr = new QueryRunner();
//自动模式
new QueryRunner(C3p0Utils.getDataSource());
}
}
2.3、使用DBUtils核心类完成数据更新操作
QueryRunner
(1)引用上述
(2)增删改的编写:
package com.zql.utils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Demo22 {
@Test
public void addProduct() throws SQLException {
//手动模式
/*QueryRunner qr = new QueryRunner();
String sql = "insert into product values(?,?,?)";
Object [] param = {13,"Daniel",23};
int i = qr.update(C3p0Utils.getConnection(), sql, param);
if(i > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}*/
//自动模式
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "insert into product values(?,?,?)";
Object [] param = {15,"Jenny1",21};
int add = qr.update(sql, param);
if(add > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
}
//自动模式
//修改
@Test
public void updateProduct() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "update product set pname = ? where pid = ?";
Object [] param = {"Wendy",15};
int add = qr.update(sql, param);
if(add > 0){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
}
//自动模式
//删除
@Test
public void deleteProduct() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "delete from product where pid = ?";
Object [] param = {15};
int add = qr.update(sql, param);
if(add > 0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
}
2.4、使用DBUtils核心类完成数据查询操作
2.4.1、ResultSetHandler接口简介
QueryRunner
ResultSetHandler 结果集处理程序 ----定义好的接口
2.4.2、JavaBean
JavaBean是满足一个特殊格式的Java类。
作用:就是封装数据。
1、实现接口。 可序列化
2、必须有私有化属性(封装)
3、为了去向外界提供属性的操作方法,必须提供getter/setter方法
4、 必须显式创建无参构造
DBUtils工具,和其他的一些常用第三方工具,都会使用JavaBean进行数据封装。
都会反射创建JavaBean对象,一般会反射无参构造进行JavaBean的实例化创建。
注意:若没有显示创建无参构造,而创建了有参构造,那么工具反射JavaBean会报错。
2.4.3、BeanHandler
应用:根据商品id查询商品、根据用户名密码查询用户
单表查询-封装伪表的第一行数据,会把伪表的第一行数据封装到一个JavaBean中。
2.4.4、BeanListHandler
单表查询-封装所有查询数据
2.4.5、MapHandler
多表查询-封装整个伪表的第一条数据。封装成一个map集合 map<String,Object>
Key:字段名
Object:字段值
2.4.6、MapListHandler
多表查询-将整个伪表数据封装起来。 一行一个map, List
2.4.7、ScalarHandler
用于SQL语句运算返回并封装单值----Object
(1)创建Product类:
package com.zql.handle;
import java.io.Serializable;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Product implements Serializable {
private int pid;
private String pname;
private String price;
public Product() {
}
public Product(int pid, String pname, String price) {
this.pid = pid;
this.pname = pname;
this.price = price;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"pid=" + pid +
", paname='" + pname + '\'' +
", price='" + price + '\'' +
'}';
}
}
(2)创建测试类:
package com.zql.handle;
import com.zql.utils.C3p0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Demo {
//BeanHandler
@Test
public void selectTest1() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "select * from product where pid = ?";
Product pr = qr.query(sql, new BeanHandler<>(Product.class), 10);
System.out.println(pr);
}
//BeanListHandler
@Test
public void selectTest2() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "select * from product";
List<Product> list = qr.query(sql, new BeanListHandler<>(Product.class));
for (Product product:list) {
System.out.println(product);
}
}
//MapListHandler
@Test
public void selectTest3() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "select * from product";
Map<String, Object> ma = qr.query(sql, new MapHandler());
System.out.println(ma);
}
//MapListHandler
@Test
public void selectTest4() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "select * from product";
List<Map<String, Object>> list = qr.query(sql, new MapListHandler());
System.out.println(list);
}
// ScalarHandler
@Test
public void selectTest5() throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
String sql = "select * from product";
Object obj = qr.query(sql, new ScalarHandler());
System.out.println(obj);
}
}
三、事务
3.1 事务的应用场景说明
在实际的业务开发中,有些业务操作要多次访问数据库。一个业务要发送多条SQL语句给数据库执行。需要将多次访问数据库的操作视为一个整体来执行,要么所有的SQL语句全部执行成功。如果其中有一条SQL语句失败,就进行事务的回滚,所有的SQL语句全部执行失败。 例如: jack给tom转账,jack账号减钱,tom账号加钱
数据准备:
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10),
balance DOUBLE
);
INSERT INTO account (NAME, balance) VALUES ('jack', 1000), (‘tom’, 1000);
模拟jack给tom转账:
3.2 操作事务
自动提交:(默认)
手动提交:
3.2.1自动提交事务
3.2.2 手动提交事务
事务有关的SQL语句:
手动提交事务使用步骤:
模拟两种场景:
3.3 事务原理
概述:事务开启之后, 所有的操作都会临时保存到事务日志, 事务日志只有在得到commit命令后才会同步到数据表中,其他任何情况都会清空事务日志(rollback,断开连接)
3.4 回滚点
概述:在某些成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管成功还是失败,前面操作都已经成功, 可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称之为 回滚点。
设置回滚点语法:
savepoint 回滚点名字
回到回滚点语法:
rollback to 回滚点名字
3.5 事务的四大特性(ACID)(注意:面试高频率)
四、使用三层思想完成转账功能
4.1 没有使用事务
(1)案例数据库
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10),
balance DOUBLE
);
INSERT INTO account (NAME, balance) VALUES ('Daniel', 1000), (‘Jenny’, 1000);
(2)案例结构
(3)案例实现
utils->C3p0Utils
package com.wx.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class C3p0Utils {
public static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static DataSource getDatasource(){
return dataSource;
}
public Connection getConnection() throws SQLException {
dataSource.getConnection();
return null;
}
}
domain->Account
package com.wx.domain;
import java.io.Serializable;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Account implements Serializable {
private int id;
private String name;
private double balance;
public Account() {
}
public Account(int id, String name, double balance) {
this.id = id;
this.name = name;
this.balance = balance;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", balance=" + balance +
'}';
}
}
web->TransferWeb
package com.wx.web;
import com.wx.service.TransferService;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class TransferWeb {
public static void main(String[] args) {
try {
String fromUser = "Daniel";
String toUser = "Jenny";
Double money = 100.0;
//service
TransferService service = new TransferService();
service.transfer(fromUser,toUser,money);
System.out.println("转账成功");
} catch (SQLException e) {
System.out.println("转账失败");
throw new RuntimeException(e);
}
}
}
service->TransferService
package com.wx.service;
import com.wx.dao.TransferDao;
import com.zql.zhuanzhang.TranceFer;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class TransferService {
public void transfer(String fromUser, String toUser, Double money) throws SQLException {
TransferDao dao = new TransferDao();
dao.jia(money,fromUser);
dao.jian(money,toUser);
}
}
dao->TransferDao
package com.wx.dao;
import com.wx.utils.C3p0Utils;
import com.zql.zhuanzhang.TranceFer;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
/**
* @Author:Daniel
* @Version 1.0
*/
public class TransferDao {
public void jia(Double money, String fromUser) throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDatasource());
String sql = "update account set balance = balance-? where name=?";
Object[] param={money,fromUser};
qr.update(sql,param);
}
public void jian(Double money, String toUser) throws SQLException {
QueryRunner qr = new QueryRunner(C3p0Utils.getDatasource());
String sql="update account set balance=balance+? where name=?";
Object[] param = {money,toUser};
qr.update(sql,param);
}
}
运行结果:
转帐前:
转账后:
4.2 使用事务
参考
建表:
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30),
money FLOAT
);
INSERT INTO account(username,money) VALUES('wency',1000),
('tom',1000),
('mary',1000);
c3p0-0.9.1.2.jar
commons-dbutils-1.4.jar
mysql-connector-java-5.0.8-bin.jar
c3po工具类
package com.wency.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.ResultSet;
public class C3p0Utils {
//创建ComboPooledDataSource对象
private static DataSource dataSource=new ComboPooledDataSource();
//获取连接的方法
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
throw new RuntimeException("服务器出错");
}
}
//获取数据源
public static DataSource getDataSource() {
return dataSource;
}
//释放资源
public static void release(Connection conn,PreparedStatement prsmt,ResultSet rs){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
conn=null;
}
if(prsmt!=null){
try {
prsmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
prsmt=null;
}
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rs=null;
}
}
}
ThreadLocalUtil类
package com.wency.utils;
import java.sql.Connection;
import java.sql.SQLException;
public class ThreadLocalUtil {
private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();
/**
*
* @return 从线程池中获取一个连接
*/
public static Connection getConnection(){
Connection conn=tl.get();//从线程中获取连接
//如果conn为空,则从线程池中取出 一个,如果不为空则直接返回原来那个
//这样做的目的是为了确保事务操作时线程不被其他线程干扰
if(conn==null){
conn=C3p0Utils.getConnection();
tl.set(conn);//将连接放到tl中去
}
return conn;
}
/**
* 开启事务
*/
public static void startTranscation(){
try {
getConnection().setAutoCommit(false);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 提交事务
*/
public static void commit(){
try {
getConnection().commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 回滚事务
*/
public static void rollback(){
try {
getConnection().rollback();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 释放资源
*/
public static void release(){
try {
getConnection().close();
tl.remove();//关闭连接之后要将该线程移除
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Account实体类
package com.wency.entity;
public class Account {
private int id;
private String username;
float money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public float getMoney() {
return money;
}
public void setMoney(float money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", username=" + username + ", money="
+ money + "]";
}
}
Dao接口
package com.wency.dao;
import com.wency.entity.Account;
public interface Dao {
//修改账户操作
int updateAccount(String username,float money);
//根据姓名查找账户
Account findAccountByName(String name);
}
Dao实现类
package com.wency.dao.impl;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.wency.dao.Dao;
import com.wency.entity.Account;
import com.wency.utils.C3p0Utils;
public class DaoImpl implements Dao {
private final String UPDATE="update account set money=? where username=?";
private final String SELECT="select * from account where username=";
public DaoImpl() {
// TODO Auto-generated constructor stub
}
@Override
public Account findAccountByName(String name) {
// TODO Auto-generated method stub
QueryRunner qr=new QueryRunner(C3p0Utils.getDataSource());
List<Account> list=null;
try {
list = qr.query(SELECT+"'"+name+"'",new BeanListHandler<Account>(Account.class));
return list.get(0);
} catch (SQLException e) {
// TODO Auto-generated catch block
}
return null;
}
@Override
public int updateAccount(String username, float money) {
// TODO Auto-generated method stub
QueryRunner qr=new QueryRunner(C3p0Utils.getDataSource());
try {
int update = qr.update(UPDATE ,money,username);
return update;
} catch (SQLException e) {
// TODO Auto-generated catch block
throw new RuntimeException("数据库操作异常");
}
}
}
Service接口
package com.wency.service;
public interface Service {
void translate(float money,String fromName,String toName);
}
Service实现类
package com.wency.service.impl;
import com.wency.dao.Dao;
import com.wency.dao.impl.DaoImpl;
import com.wency.entity.Account;
import com.wency.service.Service;
import com.wency.utils.ThreadLocalUtil;
public class ServiceImpl implements Service {
public void translate(float money, String username) {
// TODO Auto-generated method stub
}
@Override
public void translate(float money, String fromName, String toName) {
// TODO Auto-generated method stub
Dao dao=new DaoImpl();
Account fromAccount=dao.findAccountByName(fromName);
Account toAccount=dao.findAccountByName(toName);
try {
//开启事务
ThreadLocalUtil.startTranscation();
dao.updateAccount(fromName, fromAccount.getMoney()-money);
dao.updateAccount(toName, toAccount.getMoney()+money);
//提交事务
ThreadLocalUtil.commit();
} catch (Exception e) {
// TODO: handle exception
//如果出现异常,则回滚
ThreadLocalUtil.rollback();
throw new RuntimeException("操作失败");
}finally{
//最后将连接关闭
ThreadLocalUtil.release();
}
}
}
测试类
import org.junit.Test;
import com.wency.dao.Dao;
import com.wency.dao.impl.DaoImpl;
import com.wency.entity.Account;
import com.wency.service.Service;
import com.wency.service.impl.ServiceImpl;
public class TestTranslate {
@Test
public void testTranslate(){
Service service=new ServiceImpl();
service.translate(500, "wency", "tom");
}
@Test
public void testUpdate(){
Dao dao=new DaoImpl();
int updateAccount = dao.updateAccount("wency", 2000);
System.out.println(updateAccount);
}
@Test
public void testSelect(){
Dao dao=new DaoImpl();
Account account = dao.findAccountByName("wency");
System.out.println(account);
}
}