javabean mysql 增删改_jdbc(增删改查,批处理,javabean,连接池,事务)

本文介绍了如何使用JDBC连接MySQL数据库,详细讲解了DOS开启数据库服务、注册数据库驱动、数据库的增删改查操作,以及Statement与PreparedStatement的区别。此外,还探讨了JDBC的批处理功能,并通过示例展示了Statement和PreparedStatement的批处理操作。最后,文章提到了DAO模式、JavaBean以及事务处理的重要性,通过银行转账业务逻辑展示了事务的使用和ThreadLocal类在多线程中保证事务独立性的应用。
摘要由CSDN通过智能技术生成

1,JDBC (JAVA DataBase Connectivity :   java 数据库连接)

2,如何连接数据库?

e84cc6a9a4be0d92f2aa588a2d9f3acf.png

需要有一个 对应数据库的驱动jar 文件,实现Driver 接口注册,再通过DiverManger 类来获取数据库的连接。

比如:

数据库的驱动jar 包 (Mysql 对应: Mysql-connector-java-5.17.jar,不同的数据库对应不用的jar 包)放入到 web root/WEB-INF/lib/ 目录下面

3,DOS开启数据库服务的方法:

1,点击windos 键,在弹出的搜索框中,输入cmd,右键 “管理员身份运行” 打开2,输入 net start mysql ,这样就能开启mysql 服务了。

4,注册加载数据库驱动有下面三种方式

显示注册:

DriverManager.registerDriver(newcom.mysql.jdbc.Driver());

还可以使用这两种方式:

Class.forName("com.mysql.jdbc.Driver").newInstance();

Class.forName("com.mysql.jdbc.Driver"); //我们查看源码会发现,执行forName 会调用newInstance() ,所以跟上面的方法一样。

5,对数据库的 增 删 改 查

当我们使用Statement (或者 PreparedStatement)对数据库的增删改查 ,

其中 增加,删除,修改 都是执行executeUpdate()方法 操作,

查询是 executeQuary() 方法的操作,

并且查询操作会返回一个结果集(ResultSet)。

6,Statement  和 PreparedStatement 的区别:

我们可以利用 Statement 来实现对数据库的增删改查,我们只需要组织出正确的sql 语句,就可以实现。

但是我们所写的sql 语句不可以使用参数代替。也就是(?)代替。

PreparedStatement 继承于 Statement 重写了Statement 的所有方法。

PreparedStatement 允许使用不完整的 sql 语句,空缺的值使用(?)代替,直到执行的时候,再输入进去就可以了。

使用 Statement :

Statement createStatement=conn.createStatement();int executeUpdate2 = createStatement.executeUpdate("insert into user(name,password) values('1','2')");

使用 preparedStatement://创建预编译语句对象

pstmt = conn.prepareStatement("insert into user(name,password) values(?,?)");//给4个占位符赋值

pstmt.setString(1, "ww");

pstmt.setString(2, "789");//执行SQL语句(增加记录)

int n = pstmt.executeUpdate();

7,实现对数据库的操作。

package demo;

import java.sql.Connection;

import java.sql.Date;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;public classEx01 {/**

* 演示:JDBC访问数据库的操作步骤 查询*/

public static voidmain(String[] args) {

Connection conn= null;

Statement stmt= null;

ResultSet rs= null;try{//1、加载驱动程序

Class.forName("com.mysql.jdbc.Driver").newInstance();//2、通过DriverManager建立数据库连接 Driver 驱动

String url = "jdbc:mysql://127.0.0.1:3306/test";

String user= "root";

String password= "111";

conn=DriverManager.getConnection(url, user, password);//3.通过Connection获取语句对象Statement (声明)

stmt =conn.createStatement();//4.使用语句对象执行SQL语句

rs = stmt.executeQuery("select * from user");//5.遍历结果集

while(rs.next()) {//取出当前行各个字段的值

int id = rs.getInt("id");

String name= rs.getString("name");

String pwd= rs.getString("password");

System.out.println(id + " " + name + " " +pwd);

}

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}finally {//一定会执行的代码块,无论是否发生异常//6.释放相关资源

if (rs != null) {try{

rs.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

rs= null;

}if (stmt != null) {try{

stmt.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

stmt= null;

}if (conn != null) {try{

conn.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

conn= null;

}

}

}

}

package demo;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.Date;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;

import java.sql.Statement;public classEx02 {/**

* 演示:预编译语句对象PreparedStatemet的使用*/

public static voidmain(String[] args) {

Connection conn= null;

PreparedStatement pstmt= null;try{

Class.forName("com.mysql.jdbc.Driver");

String url= "jdbc:mysql://127.0.0.1:3306/test";

String user= "root";

String password= "111";

conn=DriverManager.getConnection(url, user, password);

pstmt=conn

.prepareStatement("insert into user(name,password,email,birthday) values(?,?,?,?)");//给4个占位符赋值

pstmt.setString(1, "ww");

pstmt.setString(2, "789");

pstmt.setString(3, "ww@qq.com");

pstmt.setDate(4, Date.valueOf("2016-01-01"));//执行SQL语句(增加记录)

int n =pstmt.executeUpdate();if (n > 0) {

System.out.println("增加记录成功");

}

}catch(ClassNotFoundException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}finally{if (pstmt != null) {try{

pstmt.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

pstmt= null; }if (conn != null)try{

conn.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

}

pstmt = conn.prepareStatement("delete from user where id=?");

pstmt.setInt(1, id);int n =pstmt.executeUpdate();if(n>0){return true; //操作成功

}else{return false; //操作石板

}

pstmt = conn.prepareStatement("update user set name=?,password=?,email=?,birthday=? where id=?");

pstmt.setString(1, user.getName());

pstmt.setString(2, user.getPassword());

pstmt.setString(3, user.getEmail());

pstmt.setDate(4, user.getBirthday());

pstmt.setInt(5, user.getId());int n =pstmt.executeUpdate();if(n>0){return true;

}else{return false;

}

8,JDBC 批处理SQL

可以使用 Statement  或者 PreparedStatement 对象来实现。

注意:

能够批量处理执行的SQL 必须是 INSTER UPDATE DELETE 等返回 int类型的SQL。

不能批量执行 SELECT 语句,会进行报错。另外批处理需要数据库的支持,可能有些数据库不支持。

例子一:使用Statement 批处理

package cn.edu.aynu.sushe.utils;

import java.sql.Connection;

import java.sql.SQLException;

import java.sql.Statement;public classPichuliStatement {private staticConnection conntection;private staticStatement statement;public static voidmain(String[] args) {try{

conntection=JDBCUtils.getConntection();

statement=conntection.createStatement();for (int i = 0; i < 10; i++) {

String sql= "insert into user(name,password) values('a" +i+ "','aaa" + i + "')";

statement.addBatch(sql);//batch 批量

}//批量执行将每句sql 执行的结果返回为 int【】 数组

int[] executeBatch =statement.executeBatch();for (int i = 0; i < executeBatch.length; i++) {

System.out.println(executeBatch[i] + "");

}

}catch(Exception e) {

e.printStackTrace();

}finally{//关闭流

if (conntection != null) {try{

conntection.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//关闭流

if (statement != null) {try{

statement.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

} }

}

}

数据库:

e2ea6915082be7c0e49c3935cbe3bf79.png

输出:

1

1

1

1

1

1

1

1

1

1

这个返回的int[]  当数组中的数据出现 大于 0 就代表这条sql 语句被执行成功了。如果小于0 就意味着sql 语句没有执行成功。

例子二:使用PreparedStatement 批处理

package cn.edu.aynu.sushe.utils;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;public classpichuliPreparedStatement {public static voidmain(String[] args) {try{

Connection conntection=JDBCUtils.getConntection();

String sql= "insert into user(name,password) values(?,?)";PreparedStatement prepareStatement=conntection.prepareStatement(sql);for (int i = 0; i < 10; i++) {int index = 1;

prepareStatement.setString(1, "aa"+i);

prepareStatement.setString(2, "aa"+i);

prepareStatement.addBatch();

}int[] executeBatch =prepareStatement.executeBatch();for (int i = 0; i < executeBatch.length; i++) {

System.out.println(i+"haha");

}

}catch(Exception e) {

e.printStackTrace();

}

}

}

数据库输出:

deb2bcccf749d8f319127f1247f816b3.png                

5c76097f708b23bc83e9fc633b906cb2.png

处理结果集(针对的就是执行select 语句拿到的ResultSet 对象)

package cn.edu.aynu.sushe.utils;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;public classResultSetDemo01 {/**

* @param args*/

public static voidmain(String[] args) {

Connection conntection;try{

conntection=JDBCUtils.getConntection();

Statement createStatement=conntection.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_UPDATABLE);

ResultSet rs= createStatement.executeQuery("select * from user");//光标指向第2行

rs.absolute(2);

System.out.println(rs.getInt("id"));//光标向上移动1行

rs.previous();

System.out.println(rs.getInt("id"));//光标相对向下移动2行

rs.relative(2);

System.out.println(rs.getInt("id"));//光标相对向上移动2行

rs.relative(-2);

System.out.println(rs.getInt("id"));//向下移动一行

rs.next();

System.out.println(rs.getInt("id"));

}catch(Exception e) {

e.printStackTrace();

} }

}

373d825c6898c3db769b7e4cd5c7ff43.png 输出:

127db0035531e3ef213dc9f2274f4796.png

10,JDBC 高级应用

DAO 模式  和 JavaBean

DAO (数据库操作对象 DataBase Access Object)是JDBC 下常用的模式。

保存数据时,将java bean 的属性拆分成sql语句,并保存到数据库中。

读取数据时,将数据从数据库读出来,通过setXXX方法设置到javabean 中。

看来代码怎么组成:

javabean  对象: (省略  get  set 方法)

package cn.edu.aynu.shuse.bean;public classUsers {private int id; //用户的id,自动增长,作为 linkman 的外键

private String username; //用户的姓名

private String password; //用户的密码

getXXX

setxxx

Dao 类:

package cn.edu.aynu.shuse.dao;

import java.sql.SQLException;

import java.util.List;

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanHandler;

import org.apache.commons.dbutils.handlers.BeanListHandler;

import cn.edu.aynu.shuse.bean.Users;

import cn.edu.aynu.shuse.utils.JDBCUtils;/**

* 对user表的数据操作,两方面{ (1)根据账户名,去查找密码 (2)注册添加用户的信息 }

*

* @author Administrator

**/

public classUsersDao {/**

* QueryRunner类简化了执行SQL语句的代码,它与ResultSetHandler组合在一起就能完成大部分的数据库操作,大大减少编码量。

* 针对不同的数据库操作,QueryRunner类提供的不同的方法。*/QueryRunner qr= newQueryRunner(JDBCUtils.getDataSource());/**

* (1)根据账户名,去查找密码

*

* @throws SQLException*/

public Users select(String name) throws SQLException {

String sql= "select * from user where username=?";

Users list= qr.query(sql, new BeanHandler(Users.class), name);returnlist;

}/**

* (2)注册添加用户的信息

*

* @throws SQLException*/

public voidadd(String name, String password) throws SQLException {

String sql= "insert into user(username,password) values(?,?)";

qr.update(sql, name, password);

}

}

11,JDBC 数据库连接池

为什么需要使用数据库连接池?

在JDBC编程中,每次创建和断开Connection对象都会消耗一定的时间和IO资源。

频繁地创建、断开数据库连接势必会影响数据库的访问效率,甚至导致数据库崩溃。

为了避免频繁的创建数据库连接,工程师们提出了数据库连接池技术。

什么是数据库连接池?

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立。

2ee85bb8b5c85f53685573e9726f879f.png

怎么使用数据库连接池?

【1】获取数据库连接(Connection)

既然要连接数据库就应该获取数据库连接对象(Connection),那么我们通过使用JDBC提供了javax.sql.DataSource接口

(它负责与数据库建立连接,并定义了返回值为Connection对象的方法)

Connection getConnection()

Connection getConnection(String username,String password)来拿到我们的数据库连接对象

【2】获取数据库连接池对象(DataSource)

我们习惯性的把实现了javax.sql.DataSource接口的类称为数据源,顾名思义,数据源即数据的来源。

在数据源中存储了所有建立数据库连接的信息。

常用的数据源分为两种 :

1,DBCP

2,C3P0

DBCP是数据库连接池(DataBase Connection Pool)的简称,是Apache组织下的开源连接池实现,也是Tomcat服务器使用的连接池组件。

单独使用DBCP数据源时,需要在应用程序中导入两个jar包。commons-pool.jar包 commons-dbcp.jar包

(commons-dbcp.jar包中包含两个核心类,分别是BasicDataSourceFactory和BasicDataSource,它们都包含获取DBCP数据源对象的方法。)

C3P0是目前最流行的开源数据库连接池之一,它实现了DataSource数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,

著名的开源框架Hibernate和 Spring使用的都是该数据源。

需要了解C3P0中DataSource接口的实现类ComboPooledDataSource,它是C3P0的核心类,提供了数据源对象的相关方法。

【3】使用DBCP 数据源 获取数据库的连接

当使用DBCP数据源时,首先得创建数据源对象,数据源对象的创建方式有两种。

第一种:通过BasicDataSource类直接创建数据源对象,手动给数据源对象设置属性值,然后获取数据库连接对象。

第二种:通过读取配置文件创建数据源对象,使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。(推荐使用)

第一种方式:类创建

package cn.edu.aynu.DBCP;

import java.sql.Connection;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;public classleichuangjian { public static DataSource ds = null;static{//获取DBCP的数据源对象

BasicDataSource basicDataSource = newBasicDataSource();/** 【1】设置数据库的配置信息*/

//设置连接数据库的驱动名称basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");

//设置连接数据库的路径

basicDataSource.setUrl("jdbc:mysql://localhost:3306/test");//设置数据库的登陆账号

basicDataSource.setUsername("root");//设置数据库的登录密码

basicDataSource.setPassword("111");/** 【2】设置数据库连接池的信息

**/

//设置数据库连接池初始化的连接数目

basicDataSource.setInitialSize(10);//设置数据库连接池最大活跃的连接数目

basicDataSource.setMaxActive(5);//设置数据库连接池最小闲置的连接数目

basicDataSource.setMinIdle(2);

ds=basicDataSource;

}/**

* @param args

* @throws SQLException*/

public static voidmain(String[] args) throws SQLException {//导入jar包//从数据库获取一个连接

Connection connection =ds.getConnection();

System.out.println(connection);

}

}

第二种:使用配置文件进行创建

24f09665475df1805281aab6091b290d.png

注意:这个配置文件 后缀必须是 : xxx.properties 否者创建的就是错误的

4e20838ed1f65eef2d27c46d26781173.png

package cn.edu.aynu.DBCP;

import java.io.InputStream;

import java.sql.Connection;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;public classpeizhichuangjian {/**

* @param args

* @throws Exception*/@SuppressWarnings("static-access")public static voidmain(String[] args) throws Exception {//通过配置文件来返回数据库的连接

Properties properties = newProperties();//通过类加载器拿到配置信息

InputStream inputStream = new peizhichuangjian()// .getClass()// .getClassLoader()// .getSystemResourceAsStream("ds.properties");//加载拿到的流

properties.load(inputStream);//通过工厂类创建DataSourse

DataSource createDataSource =BasicDataSourceFactory

.createDataSource(properties);

Connection connection=createDataSource.getConnection();

System.out.println(connection);

}

}

【4】使用C3P0 数据源 获取数据库的连接

当使用C3P0数据源时,首先得创建数据源对象,数据源对象的创建方式有两种。

第一种:通过ComboPooledDataSource类直接创建数据源对象,手动给数据源对象设置属性值,然后获取数据库连接对象。

第二种:通过读取配置文件创建数据源对象,使用ComboPooledDataSource读取配置文件,创建数据源对象,然后获取数据库连接对象。(推荐使用)

(其中读取配置文件,有两种方式:一种是默认的,一种是自定义的详情看下面)

一,类创建:

package cn.edu.aynu.C3P0;

import java.beans.PropertyVetoException;

import java.sql.Connection;

import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;public classleichuangjian {public static DataSource ds = null;static{

ComboPooledDataSource comboPooledDataSource= newComboPooledDataSource();//【1】配置数据源的信息

try{

comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");

comboPooledDataSource

.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test");

comboPooledDataSource.setUser("root");

comboPooledDataSource.setPassword("111");//设置连接池信息

comboPooledDataSource.setInitialPoolSize(10);

comboPooledDataSource.setMaxPoolSize(100);

ds=comboPooledDataSource;

}catch(PropertyVetoException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}/**

* @param args

* @throws SQLException*/

public static voidmain(String[] args) throws SQLException {

Connection connection=ds.getConnection();

System.out.println(connection);

}

}

二,使用配置文件进行创建:

88b5f945938ffd194430b74fe9c2bd7a.png

以xml 的方式进行的存储 这个文件存放在 src 目录下

c96166b4cffc7960ea4de0eb606a4c88.png

其中的配置代码:

jdbc:mysql://127.0.0.1:3306/test

com.mysql.jdbc.Driver

root

111

3

10

2

10

jdbc:mysql://localhost:3306/test

com.mysql.jdbc.Driver

root

111

3

10

2

10

获取数据源:

package cn.edu.aynu.C3P0;

import java.sql.Connection;

import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;public classmorenpeizhi {public static DataSource ds = null;static{//使用默认的配置

ComboPooledDataSource comboPooledDataSource = newComboPooledDataSource();

ds=comboPooledDataSource;//使用mysql-config 命名的文件创建

ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("mysql-config");

ds=comboPooledDataSource ;

}/**

* @param args

* @throws SQLException*/

public static voidmain(String[] args) throws SQLException {

Connection connection= ds.getConnection(); //拿到连接

System.out.println(connection);

}

}

12,事务实例: 银行转账(经典题目)

如何使用JDBC处理事务?

(1)在数据库操作中,一项事务是由一条或多条操作数据库的SQL语句组成的一个不可分割的工作单元

(2)只有当事务中的所有操作都正常完成,整个事务才能被提交到数据库中,如果有一项操作没有完成,则整个事务会被撤销

例如 银行的转账业务

通过 Connection 接口中提供了三个方法来针对 JDBC 处理事物。

其中有三个方法:

setAutoCommit(boolean autoCommit)// 设置自动提交 我们需要将这个方法设置为 false 不自动提交

//开启事务

public static voidstartTransaction(){try{//获取连接

Connection conn =getConnection();//开启事务

conn.setAutoCommit(false);

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

commit() // 提交   当我们的事务完成的时候,提交

//提交事务

public static voidcommit(){try{//从集合tc中得到一个连接

Connection conn = tc.get();if(conn != null){

conn.commit();

}

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

rollback()  // 回滚  当我们的事务出现异常的时候,回滚

//回滚事务

public static voidrollback(){try{//从集合tc中得到一个连接

Connection conn = tc.get();if(conn != null){

conn.rollback();

}

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

银行转账的业务逻辑

用户 zs 要向 ls 的账户上转200 元钱,该转账业务需要分成两步:

第一步:zs 的账户上需要减少200元钱

第二步:ls 的账户上需要增加200元钱

这两步操作需要都成功,事务才成功。也就是说,要么都执行成功,要么都没有执行成功。

那么就会出现两种结果,一种是commit() 执行成功,要么就需要执行 rollback () ;

13,介绍ThreadLocaL类

为什么使用ThreadLocaL 类?

Web应用程序,多用户并发访问。

一个客户端访问时,服务器启动一个线程,比如转账,在这个线程中独立完成这个事务操作,

另外一个客户端也来访问时,服务器也启动另外一个线程,在另外一个线程中独立完成转账事务操作。

要想多线程中,每个事务执行成功,必须保证每个线程有独立的Connection对象。

ThreadLocaL类介绍:

ThreadLocaL类:在一个线程中记录本地变量。

我们可以将一个Connection对象放到这个ThreadLocaL集合中,只要是这个线程中的对象都可以共享这个Connection对象,线程结束后,删除这个Connection对象。

这样保证:一个事务一个连接。

TreadLoacl本质上是一个Map,键是当前线程对象,值可以是我们的当前连接对象。

//创建一个ThreadLoacl对象,用当前线程作为key

private static ThreadLocal tc = new ThreadLocal();

14,实例

在使用数据源(DataSource )时,如果是业务处理,使用C3P0 时,不需要拿数据源对象。

Java Web应用开发的三层架构:

1、表示层(Web层):jsp和servlet2、业务逻辑层(Service层):XXXService,事务操作是在service层完成的。3、数据访问层(dao层):XXXDao

按照编写正常代码演示:

bean-->Utils ---> Dao--->service--->Servlet

先看下数据库表:

test数据库中 account 表三个字段:  id 主键自动递增,name 姓名 , money 账户的金额 (double 类型)

Account.java

package cn.edu.aynu.rjxy.bean;public classAccount {private intid;privateString name;private doublemoney;public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public doublegetMoney() {returnmoney;

}public void setMoney(doublemoney) {this.money =money;

}

}

JDBCUtils.java

package cn.edu.aynu.rjxy.utils;

import java.sql.Connection;

import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;public classJDBCUtils {//创建一个ThreadLoacl对象,用当前线程作为key

private static ThreadLocal tc = new ThreadLocal();//从c3p0-config.xml文件中读取默认配置创建数据库连接池对象

private static DataSource ds = newComboPooledDataSource();//得到数据库连接池对象

public staticDataSource getDataSource(){returnds;

}//从连接池中获取连接

public staticConnection getConnection() throws Exception{//从集合tc中获取一个Connection

Connection conn = tc.get();if(conn == null){

conn=ds.getConnection();//将conn存放到集合tc中

tc.set(conn);

System.out.println("首次创建连接:"+conn);

}returnconn;

}//开启事务

public static voidstartTransaction(){try{//获取连接

Connection conn =getConnection();//开启事务

conn.setAutoCommit(false);

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//提交事务

public static voidcommit(){try{//从集合tc中得到一个连接

Connection conn = tc.get();if(conn != null){

conn.commit();

}

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//回滚事务

public static voidrollback(){try{//从集合tc中得到一个连接

Connection conn = tc.get();if(conn != null){

conn.rollback();

}

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//关闭连接释放资源

public static voidclose(){//从集合tc中得到一个连接

Connection conn = tc.get();if(conn != null){try{

conn.close();

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}finally{//从集合tc中移除连接对象

tc.remove();

conn= null;

}

}

}

}

AccountDao,java

package cn.edu.aynu.rjxy.dao;

import java.sql.Connection;

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanHandler;

import cn.edu.aynu.rjxy.bean.Account;

import cn.edu.aynu.rjxy.utils.JDBCUtils;public classAccountDao {//根据账户名查询账户信息

publicAccount find(String name) throws Exception{

QueryRunner run= new QueryRunner(); //处理事务,不需要传 数据源对象

Connection conn =JDBCUtils.getConnection();

System.out.println("find()得到连接:"+conn);

String sql= "select * from account where name=?";

Account account= (Account)run.query(conn, sql, new BeanHandler(Account.class), newObject[]{name});returnaccount;

}//转账(可能转入也可能转出)

public voidupdate(Account account) throws Exception {

QueryRunner run= newQueryRunner();

Connection conn=JDBCUtils.getConnection();

System.out.println("update()得到连接:"+conn);

String sql= "update account set money=? where name=?";

run.update(conn, sql,newObject[]{account.getMoney(),account.getName()});

}

}

AccountService.java  转账的业务逻辑

package cn.edu.aynu.rjxy.service;

import cn.edu.aynu.rjxy.bean.Account;

import cn.edu.aynu.rjxy.dao.AccountDao;

import cn.edu.aynu.rjxy.utils.JDBCUtils;public classAccountService {//转账事务

public static void transfer(String fromName,String toName,doublebalance){try{//开启事务

JDBCUtils.startTransaction();

AccountDao dao= newAccountDao();//查询两个账户的金额

Account accountFrom =dao.find(fromName);

Account accountTo=dao.find(toName);//判断是否可以转账

if(balance

accountFrom.setMoney(accountFrom.getMoney()-balance);//设置转入账户的金额

accountTo.setMoney(accountTo.getMoney()+balance);//执行数据库更改操作

dao.update(accountFrom);

dao.update(accountTo);//提交事务

JDBCUtils.commit();

System.out.println("事务提交成功");

}else{

System.out.println("转出账户金额不足");

}

}catch(Exception e) {//回滚事务

JDBCUtils.rollback();

System.out.println("事务提交失败");

e.printStackTrace();

}finally{//释放资源

JDBCUtils.close();

}

}

}

测试转账是否能够完成

import cn.edu.aynu.rjxy.service.AccountService;public classTestTransfer {/**

* @param args*/

public static voidmain(String[] args) {//实现从zs账户上转账200到ls账户上

AccountService.transfer("zs", "ls", 200);

}

}

源码:https://github.com/gengzi/files/tree/master/%E9%93%B6%E8%A1%8C%E8%BD%AC%E8%B4%A6%EF%BC%88%E6%A1%88%E4%BE%8B%EF%BC%89

数据库:https://github.com/gengzi/files/tree/master/%E9%93%B6%E8%A1%8C%E8%BD%AC%E8%B4%A6%EF%BC%88%E6%A1%88%E4%BE%8B%EF%BC%89

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值