1,JDBC方式管理事务:
现在需要使用JDBC方式控制事务:
事务: 针对关系型数据库的一种机制
就是在执行业务操作过程中,同时执行多个sql或者多张表(添加/删除/修改),这些sql语句要么同时执行成功;
要么同时执行失败;
张三给赵又廷转账---sql全部都是使用参数化的sql语句
转账的方法(也可以自定义的方法)
public void transfer(String toName,String reveiveName,int money)
eg:
public class JDBCTransactionDemo {
public static void main(String[] args) {
//声明Connection类型变量
Connection connection = null ;
PreparedStatement ps = null ;
PreparedStatement ps2 = null ;
try {
//没有通过jdbc管理事务-----当同时执行多条sql,中间如果存在异常,第一条件语句成功了,第二条数据失败;
// 转账业务失败----->应该在jdbc操作转账的业务中加入事务操作!
//使用Jdbc控制事务--->通过获取连接对象之后,加入事务的方法
//通过工具类获取连接对象
connection = DruidJdbcUtils.getConnection();
//开启事务---->利用Connection的功能void setAutoCommit(boolean autoCommit):默认自动提交
//参数为false:禁用自动提交,需要手动提交事务
connection.setAutoCommit(false) ;
//准备sql---参数化sql
String sql = "update account set balance = balance - ? where id = ?" ;
//获取预编译对象
ps = connection.prepareStatement(sql);
//参数赋值
ps.setInt(1,500) ;
ps.setInt(2,1) ;
String sql2 = "update account set balance = balance + ? where id = ?" ;
//获取预编译对象
ps2 = connection.prepareStatement(sql2);
ps2.setInt(1,500) ;
ps2.setInt(2,2);
//分别执行更新操作
int count = ps.executeUpdate();
int i = 10/0 ;
int count2 = ps2.executeUpdate();
System.out.println(count+"---"+count2);
//提交事务: 如果没有问题,提交事务---数据在能永久更新
//Connection对象的方法:void commit()
} catch (Exception e) {
System.out.println("执行catch语句");
//出现异常,程序执行catch语句
//事务回滚
//连接对象的方法void rollback():回滚到默认在更新之前的操作
try {
connection.rollback() ;
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
/*System.out.println("异常抛出了");*/
}finally {
//任何情况下finally中的代码一定会执行的,除非 只执行这个语句之前,jvm退出了 System.exit(0) ;
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
//释放资源
DruidJdbcUtils.close(ps,connection);
DruidJdbcUtils.close(ps2,connection);
}
}
}
2,引入commons-dbutils工具类库以及使用
commons-dbutils的官网地址: Apache组织机构旗下的开源的工具类库 https://commons.apache.org/proper/commons-dbutils/
就是被用来完成jdbc操作,简化了jdbc操作的一种书写格式(查询多条记录,将这些记录封装List中)
针对原生Jdbc的建议封装
完成jdbc操作
使用步骤:
1)需要导入核心的jar包 commons-dbtils.jar
mysql驱动jar包
连接池--druid的jar包
junit单元测试:核心包junit.jar以及依赖包
2)有关commons-dbtils.jar 核心接口以及核心类有哪些
使用的执行对象:操作数据库
org.apache.commons.dbutils.QueryRunner 里面封装就是PreparedStatement
两个通用的方法
query(xxx,ResultSetHandler rsh):针对dql语句来完成查询操作
update(xxx,xx):针对dml域操作:insert into,update,delete from ....
核心接口:ResultSetHandler:针对结果集的处理
很多很多实现类
BeanListHandler:可以将查询的多条记录封装到List集合中
BeanHandler:将查询的结果集中某条记录封装到一个Java实体类中
ScalarHandler:查询出的单行单列的数据----查询出总记录数(经常用到) :聚合函数
select count(id字段) from 表名 ; -----封装到Object对象中
接口中定义一个方法---查询出总记录数----方法的返回值都使用 int或者long (目前项目中使用int够用了)
eg:
public class EmployeeDaoImpl implements EmployeeDao {
/**
* 查询所有员工
* @return 返回员工列表
*/
@Override
public List<Employee> findAll() throws SQLException {
//commons-dbutils的使用步骤
//1)导入dbutilsjar包
//2)创建数据库的执行对象
//QueryRunner
//public QueryRunner(DataSource ds)
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//3)准备sql语句---参数化的sql---查询全部员工数据
String sql = "select * from emploee" ;
//4)执行它的通用方法
//query(String sql,ResultSetHandler rsh)
//参数1:sql语句
//参数2:结果集的处理对象:接口
//最终目的将所有的记录封装到List<Employee>中
//public BeanListHandler<T>(Class<T> type) :参数是存储当前类型的字节码文件对象
List<Employee> list = qr.query(sql,
new BeanListHandler<Employee>(Employee.class));
return list;
}
/**
* 根据员工编号获取员工
* @param id 员工编号
* @return 返回就是员工实体类对象
*/
@Override
public Employee findEmployeeById(int id) throws SQLException {
//创建执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//准备sql语句---参数化的sql
String sql = "select * from emploee where id = ?" ;
//执行sql:将查询的这条记录封装到Employee类中
// public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
//参数1:sql语句
//参数2:结果集的处理:BeanHandler对象 //有参构造 public BeanHandler<T>(Class<T> class)
//参数3:给占位符号 赋值
Employee employee = qr.query(sql, new BeanHandler<Employee>(Employee.class), id);
return employee;
}
/**
* 添加员工
* @param employee
*/
@Override
public void addEmployee(Employee employee) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "insert into emploee(name,age,gender,address,salary) values(?,?,?,?,?)" ;
//执行更新
//通用的方法
//update(String sql,Object...params)
//参数1:sql
//参数2:给占位符号赋值
int count = qr.update(sql,
employee.getName(),
employee.getAge(),
employee.getGender(),
employee.getAddress(),
employee.getSalary()
);
System.out.println(count);
}
/**
* 修改员工
* @param employee 修改员工实体
*/
@Override
public void updateEmployee(Employee employee) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "update emploee set name =?,age=?,gender=?,address=?,salary=? where id = ?" ;
//更新
int count = qr.update(sql,
employee.getName(),
employee.getAge(),
employee.getGender(),
employee.getAddress(),
employee.getSalary(),
employee.getId());
System.out.println(count);
}
/**
* 根据员工编号删除员工
* @param id 员工编号
* @return 影响的行数
*/
@Override
public int deleteEmployeeById(int id) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "delete from emploee where id = ?" ;
//更新
int count = qr.update(sql,id) ;
System.out.println(count);
return count;
}
/**
* 获取员工表中总记录数
* @return 返回总条数
*/
@Override
public int getTotalCount() throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//Sql
String sql = "select count(id) from emploee" ;
//执行查询操作
//ScalarHandler实现类 ResultSetHandler:查询出的单行单列的数据----查询出总记录数(经常用到) :聚合函数
//public ScalarHandler()
Object obj = qr.query(sql, new ScalarHandler<>()) ;
//String类有万能方法:valueOf(可以传递任意类型包括Object)---->String
String s = String.valueOf(obj);
//在String--->Integer的parseInt(String s)---->int
int totalCount = Integer.parseInt(s);
return totalCount;
}
}