时间:2021-07-01 10:21:17 帮助过:2人阅读
首先,我们模拟两个银行的账号,一个给另一个汇款,首先我们要先查询一下收款人的信息,这和符合世纪逻辑,因为我们要知道收款人是否存在,同样是做一个select查询语句,方法依然使用的是前述的ParperdStatement,设置占位符的方法,判断收款人是否存在,并记录下收款方的现在余额,以便在收到钱后做一个累加。
然后重点来了,在第22行,这就是手动管理一个事物,将自动管理事物关闭,这样以上的代码就不是意见完整的事,否则他就是完整的一件事,而不会等待下面的过程,但实际上收款与汇款整体才能算上一件事,因为这涉及到两个人的账户金额变动问题,你不能只考虑其中一个人的金额变化,而将它设置为false以后上面的过程就会一起等待下面的过程。第二部是验证付款方的余额,判断是否够转。后面的过程就是收付双方金额的变动,如果你不把事物设置为手动的话,在第四步上面模拟一个代码打断一下下面代码的执行,那么后面的金额将发生错误。这里面还要说明的是conn.commit()是统一提交事务,而conn.rollback()为回滚
见名知意,就是集中到一起发送一组SQL,好处也就是效率更高,降低了数据库和程序之间的网络调用,直接给出示例代码:
@Test public void test3(){ Connection conn=null; try { conn=DBUtil.getConnection(); conn.setAutoCommit(false); //批量发送数据的前提是他们的SQL一样 String sql="insert into emp_jiawenzhe values(" + " emp_jiawenzhe_w.nextval,?,?,?,?,?,?,?)"; PreparedStatement ps =conn.prepareStatement(sql); for(int i=1;i<=108;i++){ ps.setString(1, "好汉"+i); ps.setString(2, "打劫"); ps.setInt(3, 0); ps.setDate(4, null); ps.setDouble(5, 1000.0); ps.setDouble(6, 8000.0); ps.setInt(7, 3); //将本条数据存到ps内 ps.addBatch(); //每30次批量发送一次数据 if(i%30==0){ ps.executeBatch(); //清除缓存的数据 ps.clearBatch(); } } //余下的数据单独发送一次 ps.executeBatch(); conn.commit(); } catch (SQLException e) { try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); throw new RuntimeException("批量添加员工失败",e); }finally{ DBUtil.close(conn); } }
这是一个批量插入员工的示例,首先要说明的是,批量发送SQL,前提是他们的SQL要一致,就是干的都是同样的一种事,在开始进行批处理之前,先要把事物的设置设置为手动提交,下一步就是建立SQL的变参数模型,比如说这里面我建立的是一个插入的模型,下面的for循环完全是为了省事,做出了插入108条数据的写法,当然你也可以逐一写
下面我将说明一下addBatch()这个方法,我们在写了108条数据并不是直接就写到了数据库中,他同样是要调用ParperdStatement的发送方法,但这就不是excuteQuery,写出来的东西要先放到缓存中,然后从缓存中拿到一部分数据发送数据库,再将发送完了的SQL清除缓存,下面做的是每30条发送一次的代码,调用excuteBatch发送,然后调用clearBatch清除缓存,当然最后剩下的要再一次调用excuteBatch一次性发送走,最后不要忘记提交,因为之前已经设置成了手动提交。
首先对于这块我认为不太好理解,用起来似乎也没有上面那么简单,接下来同样是引用一个示例加以说明:
这个示例是这个样子的,首先要有两张表,一张是部门表,一张是员工表,这两个表是关联的,即主表部门表的主键deptno在从表的列中也有出现,并成为从表的外键,当对主表进行插入的时候,能将从表的信息一并插入
1 @Test 2 public void test4(){ 3 //假设要添加的部门数据如下 4 String dname ="财务部"; 5 String loc="北京"; 6 //假设要添加员工的数据如下 7 String ename="张三"; 8 String job="经理"; 9 int mgr=0; 10 double sal=8000.0; 11 double comm=2000.0; 12 13 String ename2="李四"; 14 String job2="经理"; 15 int mgr2=0; 16 double sal2=5000.0; 17 double comm2=500.0; 18 19 Connection conn=null; 20 try { 21 conn=DBUtil.getConnection(); 22 conn.setAutoCommit(false); 23 //先添加部门 24 String sql ="insert into depts_jiawen " 25 + " values(depts_seq_jiawen.nextval,?,?) " ; 26 //参数二是一个数组存的是希望被ps记住的字段名字 27 PreparedStatement ps=conn.prepareStatement(sql,new String[]{"deptno"}); 28 ps.setString(1, dname); 29 ps.setString(2, loc); 30 ps.executeUpdate(); 31 32 //从ps中获取它之前记录的字段值 33 //返回的结果集中只有一种数据 34 //存的就是记录那些字段的值 35 ResultSet rs=ps.getGeneratedKeys(); 36 rs.next(); 37 int deptno=rs.getInt(1); 38 39 //再添加员工 40 sql="insert into emp_jiawenzhe values( " 41 + "depts_seq_jiawen.nextval,?,?,?,?,?,?,?) "; 42 ps=conn.prepareStatement(sql); 43 ps.setString(1, ename); 44 ps.setString(2, job); 45 ps.setInt(3, mgr); 46 ps.setDate(4, null); 47 ps.setDouble(5, sal); 48 ps.setDouble(6, comm); 49 ps.setInt(7, deptno); 50 ps.executeUpdate(); 51 52 ps=conn.prepareStatement(sql); 53 ps.setString(1, ename2); 54 ps.setString(2, job2); 55 ps.setInt(3, mgr2); 56 ps.setDate(4, null); 57 ps.setDouble(5, sal2); 58 ps.setDouble(6, comm2); 59 ps.setInt(7, deptno); 60 ps.executeUpdate(); 61 62 conn.commit(); 63 64 } catch (SQLException e) { 65 try { 66 conn.rollback(); 67 } catch (SQLException e1) { 68 // TODO Auto-generated catch block 69 e1.printStackTrace(); 70 } 71 e.printStackTrace(); 72 throw new RuntimeException("wrong",e); 73 }finally{ 74 DBUtil.close(conn); 75 } 76 }
这里面可以看到ParperdStatement中传入了两个参数,第一个和之前一样,是要执行的SQL,而第二个参数是一个字符串数组,他是希望被记住的字段名字,我的理解就是那个外键字段放到里面,为了后面取到这个外键的值传入到从表中进行更新,然后调用了getGeneratedKeys()获得了这些主键的结果集,再用int deptno=rs.getInt(1);得到对应字段的值,对于这块我实在不能明朗的解释清楚,目前我也只能说先这么记住吧,而后面的插入从表就是一个批处理操作,与前述相同。
分页就是对于一个更庞大的数据表当我们不希望看到整表时,可以分成几段呈现,这个内容就是一个固定的模式,有固定的分页公式,一目了然,用的时候直接拿过来使用就好了
示例代码:
1 @Test 2 public void test5(){ 3 int size=10; 4 int page=2; 5 6 Connection conn=null; 7 try { 8 conn=DBUtil.getConnection(); 9 String sql="select * from( " 10 + "select e.*,rownum r from ( " 11 + "select * from emp_jiawenzhe " 12 + "order by empno " 13 + ") e " 14 + ") where r between ? and ?"; 15 PreparedStatement ps=conn.prepareStatement(sql); 16 ps.setInt(1, (page-1)*size+1); 17 ps.setInt(2, size*page); 18 ResultSet rs=ps.executeQuery(); 19 while (rs.next()) { 20 System.out.println(rs.getInt("empno")+","+rs.getString("ename")); 21 22 } 23 } catch (SQLException e) { 24 25 e.printStackTrace(); 26 throw new RuntimeException("wrong",e); 27 }finally{ 28 DBUtil.close(conn); 29 } 30 }
page和size分别是分几页,每页有几个,分页的SQL写法是数据库内容,我将在数据库基本SQL使用中提到,这里面暂时先这么写着,后面的内容也就很清楚了!
未完待续!
Java——JDBC小结(5)
标签: