版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37527943/article/details/85448486
导读
1.JDBC批处理
2.JDBC事务处理
3.事务并发问题
4.JDBCTemplate
5.DAO模式
JDBC批处理
添加10000个用户到用户表
批处理:一次发送多个数据给服务器,服务器一个一个执行,提高效率
addBatch():把语句,参数添加到PreparedStatement中
executeBatch():一次把所有数据发送给服务器,有服务器一条一条执行
JDBC事务处理
可以保证多个操作要么都成功要么都失败
在Java中默认所有的操作都是自动提交
Java中什么时候考虑使用事务呢?一个业务如果涉及多个DML操作,可以使用事务控制
下单:
生成订单
生成明细
1.生成订单和生成订单明细在同一个事务中,需要使用同一个连接,Connection
2.但凡有一个出问题,就回滚,如果两个都成功,则提交
3.提交模式改成手动提交
Java事务控制步骤:
try{
建立连接;
设置为手动提交模式;
操作1;
操作2;
都成功则提交;
}catch(){
但凡有问题则回滚;
}finally{
释放连接;
}
事务相关的方法:Connection中
conn.setAutoCommit(false); --手动提交
conn.commit(); --提交
conn.rollback(); --回滚
注意点:这些仅针对于当前这个Connection对象
OrderJDBC orderJDBC = new OrderJDBC();
OrderDetailJDBC detailJDBC = new OrderDetailJDBC();
Connection conn = null;
try {
//完成下单业务
//1.生成订单编号
long orderId = orderJDBC.generateOrderId();
//先获取连接
conn = ConnectionFactory.getConnection();
//设置为手动提交模式
conn.setAutoCommit(false);
//2.生成订单
//把订单编号赋给order
order.setId(orderId);
orderJDBC.addOrder(order,conn);
//3.生成订单明细
for(int i=0; i<list.size();i++) {
list.get(i).setOrderId(orderId);//生成的订单号赋给明细
detailJDBC.addOrderDetail(list.get(i),conn);
}
//都成功提交
conn.commit();
return true;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//如果有问题,则回滚
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return false;
}finally {
DBUtils.close(conn);
}
事务并发问题
事务并发引起的问题(等级越来越高,并发性越差):
1.脏读:一个事务读到了另一个事务未提交的更新数据,
应该要避免
2.不可重复读:一个事务期间两次读取同一个数据结果不同,
通常不需要避免的
3.虚读/幻影读:一个事务期间两次读取的同一个统计结果不同(比如求和,求平均)
通常不需要避免的
事务隔离级别:
0 TRANSACTION_NONE:不支持事务
1 TRANSACTION_READ_UNCOMMITTED:脏读
2 TRANSACTION_READ_COMMITTED:避免脏读
4 TRANSACTION_REPEATABLE_READ:避免不可重复读
8 TRANSACTION_SERIALIAZABLE:避免虚读
事务隔离级别越高,并发性越差
Oracle只支持2,8, 默认是2
conn.setTransactionIsolation(level);//可以写名字,也可以写数字
JDBCTemplate
封装通用的增删改查步骤
分为两种,一种是针对于增删改,另一种是针对查封装
对于增删改
package com.hwua.util;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 设置占位符值的接口
* @author Mary
*
*/
public interface PreparedStatementSetter {
//设置占位符的值
public void setValues(PreparedStatement pstmt)
throws SQLException;
}
针对查
package com.hwua.util;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 处理结果集的接口
* @author Mary
*
*/
public interface ResultSetHandler {
/**
* 处理结果集
* @param rs 结果集
* @throws SQLException
*/
public void handleRS(ResultSet rs)
throws SQLException;
}
package com.hwua.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 模版类
* 封装通用的增删改,查方法
* @author Mary
*
*/
public class JDBCTemplate {
//增删改
//这里要求实现PreparedStatementSetter接口的对象,是面向接口编程
public int update(String sql,PreparedStatementSetter setter)
throws SQLException {
//1,2
Connection conn = ConnectionFactory.getConnection();
//3
PreparedStatement pstmt = conn.prepareStatement(sql);
//4
//先设置占位符的值
if(setter!=null) {
setter.setValues(pstmt);
}
//执行
int rows = pstmt.executeUpdate();
//6
DBUtils.close(pstmt, conn);
return rows;
}
//查询
public void query(String sql,
PreparedStatementSetter setter,
ResultSetHandler handler) throws SQLException {
//1,2
Connection conn = ConnectionFactory.getConnection();
//3
PreparedStatement pstmt = conn.prepareStatement(sql);
//4
if(setter!=null) {
setter.setValues(pstmt);
}
ResultSet rs = pstmt.executeQuery();
//5.处理结果集
if(handler!=null) {
handler.handleRS(rs);
}
//6.
DBUtils.close(rs, pstmt, conn);
}
}
测试类中的实现
public int addUser(User user) throws SQLException {
String sql = "INSERT INTO t_user (id,username,password,sex,"
+ "id_number,tel,addr) "
+ "VALUES(t_user_id_seq.NEXTVAL,?,?,?,?,?,?)";
//调用通用的增删改方法
return update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setInt(3, user.getSex());
pstmt.setString(4, user.getIdNumber());
pstmt.setString(5, user.getTel());
pstmt.setString(6, user.getAddr());
}
});
}
/**
* 通过用户名查找用户
* @param username:用户名
* @return 查找到的用户信息 null:没有对应的用户
* @throws ClassNotFoundException
* @throws SQLException
*/
public List<User> queryUser(String username) throws SQLException {
List<User> list = new ArrayList<>();
String sql = "SELECT id,username,password,sex,id_number,"
+ "tel,addr FROM t_user WHERE username=?";
query(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
//放置设置占位符的值的代码
pstmt.setString(1, username);
}
}, new ResultSetHandler() {
@Override
public void handleRS(ResultSet rs) throws SQLException {
//放置结果集处理的代码
if(rs.next()) {
User user = new User(rs.getLong(1), rs.getString(2), rs.getString(3), rs.getInt(4), rs.getString(5),
rs.getString(6), rs.getString(7));
list.add(user);
}
}
});
return list;
}
DAO模式
DAO:Data Access Object,数据访问对象
把数据访问细节封装起来
一个原子性的增删改查封装成一个方法
一个表对应一个DAO
一个接口+一个实现类
命名:
IUserDao UserDaoImpl
IOrderDao OrderDaoImpl
包:
com.hwua.dao com.hwua.dao.impl
Java<==>JDBC<==>数据库SQL
登录:
输入用户和密码,判断是否正确
利用查询查找对应的用户是否存在
注册:
输入各种信息
查询是否合法
合法添加到数据库
分层思想:
界面层<==>业务逻辑层<==>DAO层
界面层:与用户打交互,具体做这个业务调用业务逻辑层
业务逻辑层:完成这个业务
可能涉及到与数据库的交互调用DAO
DAO层:数据访问层