JDBC事务控制
1.什么是事务:一个包含多个步骤或者业务操作,如果业务或者多个业务被事务管理,则这么多个步骤要么同时成功,要么同时失败,这些步骤是一个整体不可分割.
2.操作:
事务的操作需要,Connection对象.事务方法 con=DBUtil.getConnection().
开启事务:mysql----->start transaction
提交事务:commit
回滚事务:rollback
3.使用Connection对象来管理事物
开启事物:setAutoCommit(boolean autoCommit):-->指定该方法里面传入false值,表示开启事务,开启事务是 在所有sql语句执行之前
提交事务:commit():--->当前面所有的sql语句执行完毕(不出错)的时候才能提交事务
回滚事务:rollback():--->当执行事务中sql语句时候,如果失去了语句发生异常那么就会回滚事务,所以回滚事务的代码一般都是放在catch语句块中
4.示例代码:
// 含有事务的转账
public static void transform02() {
// 让张三给李四转账10000钱
/*
* 首先让张三的钱减少10000
* 然后让李四的钱增加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(boolean autoCommit):
Connection con = DBUtil.getConnection();
try {
con.setAutoCommit(false);
// 通过con获取预处理对象 先让张三的钱减少10000
ps01 = con.prepareStatement(sql01);
ps01.setDouble(1, money);
ps01.setString(2, username01);
// 执行sql语句
int count = ps01.executeUpdate();
// 手动制造一个异常
int i = 1 / 0;
// 再让李四的钱增加10000
// 通过con获取预处理对象
ps02 = con.prepareStatement(sql02);
ps02.setDouble(1, money);
ps02.setString(2, username02);
// 执行sql语句
int coun02 = 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();
}
}
}
连接池
1.什么是连接池
其实就是一个容器,在这个容器当中存放着多个连接对象
当系统开始运行的时候,可以让系统提前创建多个连接对象,放到容器里面(连接池),当客户端需要连接对象时,看洋葱常量池里面申请一个连接,去访问数据库的时候,当该连接使用完毕的时候,不再释放归还给系统,而是把这个连接对象还给连接池.
2.好处:
可以大大节省系统的开销
可以提高访问速度
3.实现操作
javax.sql
JNDI--->java命名和目录接口
使用JNDI降低程序和数据库耦合度,是你的程序更加方便配置和维护以及部署.
是javaEE中规范中的重要规范之一.是EJB的相关知识.
DateSource接口 他里面并不提供具体的实现么事由驱动程序供应商(数据库厂商提供)
1.c3p0---->一套数据库连接池的技术
2.druid--->也是一套数据库连接池技术,由阿里巴巴提供
3.c3p0数据库连接池技术
步骤:
1.找到 c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar
2.把两个jar包植入到工程的classpath类路径下(lib包下),不要忘记导入mysql驱动jar包,mysql-connector-java.jar
3.在src下面,定义配置文件;c3p0.properties或者c3p0-config.xml
4.获取DateSource对象:通过工厂方式来实现,DruidDateSourceFactory
5.从连接池中获取连接对象,:getConnection()
JDBCTemplate
1.Spring框架挺可怜对JDBC操作的简单封装,使用JDBCTemplate对象来简化JDBC开发流程
2.步骤
1.从官网找到spring-jdbc相关的jar包导入工程路径下(lib文件夹)
2.创建JDBCtemplate对象,依赖于DateSource连接池(数据源)
3.使用HDBCTemplate对象中的api方法实现crud操作
DML操作:update();
DQL操作:查询不用select用query
query();将查询的结果集服装为javaBean对象
query()方法的参数:RowMapper
手动装配:使用匿名内部类,自定义装配查询的每条记录
自动装配:使用Spring提供的BeanPropertyRowMapper实现类,完成对数据的自动装配
具体操作如下:new BeanPropertyRowMapper<类型>(类型.class)
queryForMap():将查询结果封装成map集合,只能封装一条记录:键key是字段名,值value是字段 值,结果集记录数只能是1
queryForList():将结果集服装为List集合,在list集合中含有多条记录,每天一条记录都是一个map集合,List<Map<Object,Object>> list:
queryForObject();将结果封装成为一个对象,一般用于聚合函数,查询总记录数 int count()
具体操作:
// 增删改动作
// 修改数据
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
}