1、事务
几行代码一起执行,要么都成功,要么都失败,commit,rollback
public class TestTransaction {
@Test
public void test(){
//添加一个员工
Connection conn = DBUtilConnection.getThreadConnection();
try {
//开启事务
conn.setAutoCommit(false);
addEmp();
System.out.println("员工添加成功");
int num = 5/0;
//添加一个部门
addDept();
System.out.println("部门添加成功");
conn.commit();//提交事务
} catch (Exception e) {
//如果出异常,回滚
try {
conn.rollback();//回滚事务
System.out.println("发生异常,数据回滚");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
public int addDept(){
String sql = "insert into dept values(?,?,?)";
Object[] params = {50,"武术部","武当山"};
int i = DBUtilConnection.executeUpdate(sql, params);
return i;
}
public int addEmp(){
Emp emp = null;
try {
emp = new Emp(1113,"张三丰","拳师",7902,new SimpleDateFormat("yyyy-MM-dd").parse("2022-2-2"),900.0,null,50);
} catch (ParseException e) {
e.printStackTrace();
}
String sql = "insert into emp values(?,?,?,?,?,?,?,?)";
Object[] params = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
int i = DBUtilConnection.executeUpdate(sql, params);
return i;
}
}
注意:事务跟连接相关,如果事务属于不同的连接,那么就无法回滚。 你要控制事务,首先要搞明白是不是同一个连接。
2、批处理
批处理就是很多句sql一起处理
1、不同类型的sql批处理
public void test1() throws Exception {
//测试批处理
//不同类型的sql语句来一起处理---添加一个部门,删除一个部门
Connection conn = DBUtilConnection.getThreadConnection();
Statement stmt = conn.createStatement();
String addSql = "insert into dept values(80,'测评部','成都')";
String deleteSql = "delete from dept where deptno=60";
//添加到批处理---装车
stmt.addBatch(addSql);
stmt.addBatch(deleteSql);
int[] ints = stmt.executeBatch();
System.out.println(Arrays.toString(ints));
}
2、相同类型大量数据的批处理--10008条部门---100条为一批去处理
@Test
//这个测试相同类型多条sql的批处理
public void test() throws SQLException {
Connection conn = DBUtilConnection.getThreadConnection();
String sql = "insert into dept values(?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
//真正的生成批处理的sql
for(int i=1;i<=10008;i++){
pstmt.setInt(1,i);
pstmt.setString(2,"部门"+i);
pstmt.setString(3,"地址"+i);
pstmt.addBatch();//加入到批处理
if(i%100==0){
int[] ints = pstmt.executeBatch();
System.out.println(Arrays.toString(ints));
}
}
//最后这模不尽的
int[] ints = pstmt.executeBatch();
System.out.println(Arrays.toString(ints));
}
3、BeanUtils组件的使用
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
说白了,BeanUtils这个工具是简化对反射的操作的
@Test
public void test() throws Exception {
//BeanUtils是操作对象的,基于反射操作
Dept dept = new Dept(10,"研发部","北京");
//复制对象
// Dept dept1 = (Dept)BeanUtils.cloneBean(dept);
// System.out.println(dept1==dept);
//设置指定的属性
//BeanUtils.setProperty(dept,"dname","开发部");
//System.out.println(dept);
//BeanUtils.copyProperty(dept,"dname","工程部");
//System.out.println(dept);
//复制所有的属性
//Dept d2 = new Dept();
//BeanUtils.copyProperties(d2,dept);
//System.out.println(d2);
//把所有的属性转换为Map集合
Map<String, String> map = BeanUtils.describe(dept);
map.remove("class");
//System.out.println(map);
//把集合转为对象
Dept d1 = new Dept();
map.put("deptno","100");
BeanUtils.populate(d1,map);
System.out.println(d1);
}
4、DBUtils组件使用
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
public class TestDBUtils {
@Test
public void test() throws SQLException {
QueryRunner runner = new QueryRunner();
Object query = runner.query(DBUtilConnection.getThreadConnection(), "select count(*) from emp", new ScalarHandler<>());
System.out.println(query);
}
@Test
public void test3() throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "select ename,dname from emp join dept on emp.deptno=dept.deptno";
List<Object[]> query = runner.query(DBUtilConnection.getThreadConnection(), sql, new ArrayListHandler());
for(Object[] arr : query){
System.out.println(Arrays.toString(arr));
}
}
@Test
public void test2() throws SQLException {
QueryRunner runner = new QueryRunner();
List<Emp> emps = runner.query(DBUtilConnection.getThreadConnection(), "select * from emp", new BeanListHandler<>(Emp.class));
System.out.println(emps);
}
@Test
public void test1() throws SQLException {
QueryRunner runner = new QueryRunner();
int res = runner.update(DBUtilConnection.getThreadConnection(), "delete from dept where deptno=1");
System.out.println(res);
}
}
5、DBUtils的仿写
DBUtils的总体思路是提供一个结果集的处理器,这个处理器去处理不同的结果集,得到不同的返回值。
5.1 编写处理器的父接口-MyResultSetHandler
public interface MyResultSetHandler<T> {
T handle(ResultSet rs);//这个处理器的父接口规定了必须有一个处理结果集的方法
}
5.2 编写QueryRunner - MyQueryRunner
public class MyQueryRunner {
//你给我构造一个数据源,我用这个连接池里面的连接---前提是没有事务
private DataSource ds;
public MyQueryRunner(DataSource ds){
this.ds = ds;
}
//查询的方法
public <T> T query(String sql,MyResultSetHandler<T> rsh,Object... params){
Connection conn= null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = ds.getConnection();
pstmt = conn.prepareStatement(sql);
if(params!=null){
for(int i=0;i<params.length;i++){
pstmt.setObject(i+1,params[i]);
}
}
rs = pstmt.executeQuery();
T t = rsh.handle(rs);
return t;
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(rs,pstmt,conn);
}
return null;
}
//增删改的方法
public int update(String sql,Object... params){
int res = -1;
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = ds.getConnection();
stmt = conn.prepareStatement(sql);
//设置参数
if(params!=null){
for(int i=0;i<params.length;i++){
stmt.setObject(i+1,params[i]);
}
}
//执行sql
res = stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(null,stmt,conn);
}
return res;
}
public void closeAll(ResultSet rs, Statement stmt, Connection conn){
try {
if(rs!=null){
rs.close();
rs = null;//提醒垃圾回收
}
if(stmt!=null){
stmt.close();
stmt = null;//提醒垃圾回收
}
if(conn!=null){
conn.close();
conn = null;//提醒垃圾回收
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.3 编写处理器的子类
5.3.1 BeanListHandler
这个处理器把一个结果集处理成一个对象集合
public class MyBeanListHandler<T> implements MyResultSetHandler<List<T>> {
Class<T> clazz;
public MyBeanListHandler(Class<T> clazz){
this.clazz = clazz;
}
@Override
public List<T> handle(ResultSet rs) {
//如何创建一个泛型对象---你只给我泛型是没法创建对象的,还必须给我这个类
List<T> list = new ArrayList<>();
try {
while(rs.next()){
T t = clazz.newInstance();
int columnCount = rs.getMetaData().getColumnCount();
for(int i=1;i<=columnCount;i++){
String columnName = rs.getMetaData().getColumnName(i);
Object value = rs.getObject(columnName);
BeanUtils.setProperty(t,columnName,value);
}
list.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return list;
}
}
5.3.2 MyArrayListHandler
public class MyArrayListHandler implements MyResultSetHandler<List<Object[]>>{
@Override
public List<Object[]> handle(ResultSet rs) {
List<Object[]> list = new ArrayList<>();
//把结果集处理成这么一个数组就可以了
try {
//查询列的数量就是我数组的长度
int columnCount = rs.getMetaData().getColumnCount();
while(rs.next()){
Object[] row = new Object[columnCount];
for(int i=0;i<row.length;i++){
row[i] = rs.getObject(i+1);
}
list.add(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
5.3.3 查询第一行第一列
public void test() throws SQLException {
Object res = runner.query("select ename from emp where empno=7369", new MyResultSetHandler<Object>() {
public Object handle(ResultSet rs) {
try {
if (rs.next()) {
return rs.getObject(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
});
System.out.println(res);
}
5.4 编写工具类
public class MyDBUtil {
private static String driver = "";
private static String url = "";
private static String username = "";
private static String password = "";
private static DruidDataSource ds = new DruidDataSource();
static {
Properties prop = new Properties();
InputStream is = MyDBUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
prop.load(is);
driver = prop.getProperty("jdbc.driver");
url = prop.getProperty("jdbc.url");
username = prop.getProperty("jdbc.username");
password = prop.getProperty("jdbc.password");
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
ds.setMaxActive(100);//最大活动数量100个
ds.setInitialSize(20);
ds.setMinIdle(20);
ds.setMaxWait(1000*60);
} catch (IOException e) {
e.printStackTrace();
}
}
//封装一个获取MyRunner的方法
public static MyQueryRunner getRunner(){
return new MyQueryRunner(ds);
}
}

2023

被折叠的 条评论
为什么被折叠?



