- jdbc事务
- 连接池概念
- C3P0
- Driud
- JDBC Template
JDBC事务控制
事务是一个包含多个步骤或者业务操作。如果这个业务或者多个步骤被事务管理,则这多个步骤要么同时成功,要么回滚,这多个步骤是一个整体,不可分割
操作:开启事务:start transaction
提交事务:commit
回滚事务:roolback
在JDBC中,使用Connection对象管理事务
开启事务:setAutoCommitc(boolean autoCommit):执行该方法里面传入 false时,手动开启事务 --->在执行sql之前开启事务
提交事务:commit(); --->当所有的sql语句执行完毕 提交事务
回滚事务:rollback();--->当事务中发生异常时,回滚事务,放在catch语句块中
private static PreparedStatement ps01 = null;
private static PreparedStatement ps02 = null;
public static void main(String[] args) {
}
// 带事务的转账
public static void transform() {
// 张三转给李四10000
// 定义实现转账的两条sql
double money = 10000;
String username01 = "张三";
String username02 = "李四";
String sql01 = "update account set balance =balance-? where username=?";
String sql02 = "update account set balance =balance+? where username=?";
//获取Connection对象以用来手动开启事务 setAutoCommit()
Connection con = DBUtil.getConnection();
try {
//让张三的钱减少10000
con.setAutoCommit(false);
//通过con获取预处理执行对象
ps01 = con.prepareStatement(sql01);
ps01.setDouble(1, money);
ps01.setString(2, username01);
//执行sql语句
int count01 = ps01.executeUpdate();//获取影响记录条数
//手动制造异常 int i = 1 / 0;
//让李四的钱增加10000
ps02 = con.prepareStatement(sql02);
ps02.setDouble(1, money);
ps02.setString(2, username02);
//执行sql语句
int count02 = ps02.executeUpdate();//获取影响记录条数
//提交事务
con.commit();
System.out.println("转账成功");
} catch (Exception e) {
//发生异常 事务回滚
try {
con.rollback();
System.out.println("转账失败");
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//释放连接
try {
ps02.close();
ps01.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
连接池
什么是连接池?
其实就是一个容器,与线程池概念相似,在这个容器中存放了多个连接对象,当 系统开始运行时,可以让系统提前创建多个连接对象,放到连接中,当客户端需要连 接对象时,可以从连接池中申请一个连接去访问数据库,当连接使用完毕时,不再释 放归资源,而是把这个连接对象归还给连接池
优点:
大大节省系统开销
提高访问速度
实现操作:
javax.sql
操作数据库额外功能包
JNDI: java naming and directory interface java命名和目录接口
使用JNDI降低程序和数据库之间的耦合度,使你的程序更加方便的配置
是JavaEE规范中的重要规范之一 。 是EJB相关知识
将大量暴露在外部的代码放入DataSource,通过它来管理控制
DataSource接口里并不提供具体的实现,而是由驱动程序供应商(数据库厂 商)提供
1.c3p0是数据库连接池的一套技术
2.druid
c3p0:数据库连接池技术
步骤:
-
准备jar包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.12.jar
-
植入到工程的classpath下
-
定义配置文件:
文件类型:c3p0.properti 或者 c3p0-config.xml
路径:放到classpath类路径下(build--->classes文件下) 对于工程 来说直接放到src下(直接会被解析到build--->classes下)
-
获取DataSource对象:数据库连接池对象 通过实例化
CombopooledDataSource
来获取 -
从连接池中获取连接对象 getConnection()
druid:数据库连接池技术
步骤:
- 准备jar包
druid-1.0.9.jar
- 定义配置文件:使用properties文件类型,名字随便起
- 手动加载配置文件信息:Properties集合
- 获取DataSource对象:数据库连接池对象 通过工厂方式实现
DruidDataSourceFactory
- 从连接池中获取连接对象 getConnection()
JDBC Template
将获取连接对象和执行对象隐藏到内部,直接获取数据源就可以对数据库操作
-
Spring框架提供了对JDBC操作的简单封装,使用JDBCTemplate对象来简化JDBC开发流程。
-
步骤:
-
从官网下载对应的spring-jdbc相关的jar包,导入工程类路径下,放到lib文件夹下面即可
-
创建JDBCTemplate对象。依赖于DataSouce连接池(数据源)
-
使用JDBCTemplate对象中的api方法实现crud操作
-
DML操作: update()
-
DQL操作: 查询 不用select,使用query
-
query(): 将查询的结果集封装成JavaBean对象
-
query()方法的参数:RowMapper
-
手动装配:使用匿名内部类,自定义装配查询的每条记录值
List<Account> list = tp.query(sql, new RowMapper<Account>() { @Override public Account mapRow(ResultSet set, int arg1) throws SQLException { //封装查询到每一条记录值 Account account = new Account(); account.setId(set.getInt(1)); account.setUsername(set.getString(2)); account.setBalance(set.getDouble(3)); return account; } });
-
自动装配:使用Spring提供的BeanPropertyRowMapper实现类,完成对数据的自动装配
具体操作-->new BeanPropertyRowMapper<类型>(类型.class)
-
-
-
queryForMap(): 将查询的结果集封装成map集合,只能封装一条记录:键key是字段名,值value是字段值,结果集记录数只能是1
-
queryForList():将结果集封装成List集合,在list集合中有多条记录,每一条记录都是一个map集合
List<Map<Object,Object>> list ;
- queryFoObject():将结果集封装成一个对象,一般用于聚合函数 查询总记录数 int count()a
-
-
具体操作:
// 增删改动作 // 修改数据 public static void modifyData() { int count = jdbcTemplate.update("update account set username = ? where username = ?", "小五","王五"); System.out.println(count); } // 删除数据 public static void deleteData() { int count = jdbcTemplate.update("delete from account where username = ?", "小五"); System.out.println(count); } // 插入一条数据 public static void insertDate() { int count = jdbcTemplate.update("insert into account values(null,?,?)", "王五",5000); System.out.println(count); } public static void test() { // 查询张三的这条信息 封装到账户对象中 String username = "张三"; String sql = "select * from account where username = ?"; Map<String, Object> map = jdbcTemplate.queryForMap(sql,username); System.out.println(map);// {id=1, username=张三, balance=20000.0} } // 简化手动封装的方法 public static void queryAll() { String sql = "select * from account"; // Incorrect column count: expected 1, actual 3 List<Map<String, Object>> list = jdbcTemplate.queryForList(sql); System.out.println(list); } // 使用query方法优化queryBean方法 public static void queryBean2() { List<Account> list = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); System.out.println(list); } // 将查询到结果集封装成JavaBean对象 public static void queryBean() { String sql = "select * from account where username = '张三'"; // RowMapper<T> List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>() { @Override public Account mapRow(ResultSet set, int arg1) throws SQLException { // 封装查询到每一条记录值 Account account = new Account(); int id = set.getInt(1); String username = set.getString(2); double balance = set.getDouble(3); account.setId(id); account.setUsername(username); account.setBalance(balance); return account; } }); System.out.println(list);// [Account [id=1, username=张三, balance=20000.0]] } // 查询总记录 查询account表中的所有记录数 public static void queryTotalNum() { // queryFoObject() Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class); System.out.println(count);// 4 }
-
-