`

j2ee08:jdbc02:事务处理、滚动结果集分页、复杂sql分页

    博客分类:
  • j2ee
 
阅读更多
基本概念:
第一个知识点:事务(transaction交易的意思):
事务是不可分割的,也就是原子性,例如转账,涉及到两个select语句,这两条语句要么全部执行,要么全部不执行
事务是有结构的:在java中靠的是异常处理,在try语句块中写内容(就是异常处理结构)
  内容是:
    1.开启一个事务:conn.setAuotCommit(false)手动提交
    2.执行sql1,执行sql2.....执行sqln(执行多条语句)
    3.提交conn.commit()
 如果发生异常,将在catch中执行回滚:4.conn.rollback();
 最后在finally中关闭数据库资源
onn.commit()和conn.rollback()是边界语句
-----
自动提交的单位是一条sql语句,关闭自动提交并使用commit就一次执行多条了
设置成非自动提交,我们就认为这句话是开启事务,因为执行多条语句了(事务就是在执行多条数据)
在执行多条sql语句的时候是先把sql语句的结果放在缓存里,当commit的时候才正式提交
注意:连接对象是事务的前提,commit和rollback是事务的正常关闭和异常关闭。conn开启的,也要conn结束。
第二个知识点:关于分页:
第一.使用滚动结果集分页:其实就是在以前正常的查询的基础上加了一些东西
    思路:1.在方法上加两个形式参数,分别代表页数page和每页的记录数pagesize
          2.在使用createStatement方法的时候,给这个方法加上两个参数,让这个方法创建的语句对象能够滚动只读。
          3.执行sql语句产生结果集对象,然后给结果集对象绝对定位,定位到begin位置,begin是通过两个形参做运算之后的结果(这也就是形参的作用了)
            绝对定位能够定位到某一页的第一行记录。
          4.定位到某一页的第一行记录之后,就开始for循环,循环遍历这一页的每行内容。
          5.考虑到最后一页可能数据不足,写一个if语句if(!rs.next()){break}
          注意:在方法体中要先利用参数算出起始行。
  滚动结果集的缺点:滚动结果集能够上下滚动,还能够绝对定位和相对定位,之所以能够实现这些功能,是因为在使用滚动结果集的时候,
                   他把每一条记录都加上了一个链表,这样把每一条记录都连接到了一起。但是,这样就导致一个缺点,就是会对客户端和
                   服务器端的内存带来极大的消耗,因此不能处理海量数据。
第二:使用select语句完成分页功能:其实跟以前正常些的查询语句一样,不一样的地方就是select语句不一样
     思路:1.就是在select语句中下文章,如果想对某个表进行分页查询,先给这个表中的记录加上行号,使用rownum就能够加上行号。
           2.现在要操作的是这个带行号的表,也就是要查询的是这个带行号的表,在查询的时候对这个表加上where条件,条件是
             查询记录从哪条开始,哪条结束
            注意:在方法体中要先利用形式参数算出要查询的起始行和结束行

区别:第一种由于需要用到滚动结果集,但是滚动结果集在Statement接口中,因此要使用createStatement方法给他分配结果集的滚动参数。
      第二种分页由于在复杂select语句中用到了?传值的形式,因此是预编译语句,要使用PrepareStatement。
          
   第一种分页:是个for循环,因此有必要判断!rs.next()。注意:这种滚动结果集的方式只是在上面一行代码中定位了这一页的起始行,但是并没有结束行,如果用
        while语句循环的话,就相当于从当前记录一直循环到最后一条记录了。为了只循环这一页,因此使用for循环,循环条件是i小于这个页的总行数。
 for(int i=1;i<=pagesize;i++){
    System.out.println(rs.getString("cid")+" "+rs.getString("cname")+" "+rs.getInt("xf"));
                if(!rs.next()){
                 break;
                }
   }    
  第二种分页:用的是while循环,当条件满足才会进循环,因此不用考虑条件不满足的情况,也就是不用!rs.next()。注意:这行while循环上面设置了起始行的位置和
           结束行的位置,因此可以用while循环。也就是说select语句中已经规定好了起始行和结束行。
      while(rs.next()){
    System.out.println(rs.getString("cid")+" "+rs.getString("cname")+" "+rs.getInt("xf"));
   }
 
代码实现:
第一:使用批处理executeBatch,完成事务操作
package updateTest;
import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Random;
import comm.dbHandler;
//关于批处理executeBatch,批处理添加。批处理就是在事务的基础上使用executeBatch
//事务提交的方式是事务之内的所有语句都会一起提交,批处理是在事务的基础上加了executeBatch,也就是不是所有的执行语句一起提交,而是规定每次提交几个
public class TestBatch {
 private static  ResultSet rs=null;
 public static int executeBatch(){
 //String sql="insert into cou values(?,?,?)";
  String sql="insert into cou "+" values(?,?,?)";
    Connection conn=dbHandler.getConnection();
    PreparedStatement pstmt=null;
    int count=0;
    try {
  conn.setAutoCommit(false);
  pstmt=conn.prepareStatement(sql);
  Random random=new Random();
  for(int i=1;i<=4;i++){//这里说明一共有4条数据
   int xuefen=2+random.nextInt(20-2+1);
   pstmt.setString(1, "3"+i);
   pstmt.setString(2, "同学"+i);
   pstmt.setInt(3, xuefen);
   pstmt.addBatch();//添加到批处理
   count++;
  if(i%10==0){//当批量处理列表中积累了10条sql语句
   //通过预备语句对象,一次性执行批处理列表中的
   //10条sql语句
   pstmt.executeBatch();//当缓存中有十条语句的时候就执行这批语句。从客户端发送到服务器端,从java程序发送到oracle。(一边发送一边处理)
   //清空批处理列表
   pstmt.clearBatch();//清空这一批列表,准备接受下一批
  }
  }
  pstmt.executeBatch();//这是给最后一次用的
  conn.commit();
  
 } catch (Exception e) {
  try {
   conn.rollback();
   count=0;//注意回滚后把数清零
  } catch (SQLException e1) {
   e1.printStackTrace();
  }
  e.printStackTrace();
 }finally{
  dbHandler.getClose(rs, pstmt, conn);
 }
 return count;
 } 
 public static void main(String[] args) {
  int n=executeBatch();
  System.out.println(n);
 }
}
 
 
第二:不使用批处理executeBatch,完成事务操作
package updateTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import comm.dbHandler;
/**针对user表,编写一个Java应用程序,该程序提供一个修改用户email的方法,要求将email设置成"用户名@sina.com"。这个修改方法的签名如下:
updateEmail(int id),id指的是用户的编号。更新完成之后,通过查询显示更新的结果。
 *
 */
//注意:这里面每个方法都是可以用的
public class chu {
 private static Statement  stmt=null;
 //private static Connection conn=dbHandler.getConnection();//打开连接,这虽然是每个方法都会用到的,但是如果这个方法当成全局变量,只能操作一个方法,当操作多一个方法的时候连接已经关闭。因为这个属性要在每个方法中重复声明一次
 private static PreparedStatement pstmt=null;
 private static ResultSet rs=null;
 //不带参数的方法
/* public static void updateing(){
   Connection conn=dbHandler.getConnection();
  String sql="update book set name='java面向对象' where id=?";
  //String sql="update book set name='java面向对象'";
  int rows=0;
  try {
   PreparedStatement pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, 1002);
   rows=pstmt.executeUpdate();
   if(rows==1){
    System.out.println("修改成功");
    chu.search();
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  }
 }
 //带参数的方法
 public static void updateing(int bid){
  Connection conn=dbHandler.getConnection();
  String sql="update book set name='java面向对象' where id=?";
  int rows=0;
  try {
   PreparedStatement pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, bid);
   rows=pstmt.executeUpdate();
   if(rows==1){
    System.out.println("修改成功");
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  }
 }*/
 //带参数的方法
  public static void updateing1(int bid){
   Connection conn=dbHandler.getConnection();
   String sql="update book set name=? where id="+bid;
   int rows=0;
   try {
    PreparedStatement pstmt = conn.prepareStatement(sql);
    pstmt.setString(1, getUserName(bid)+"a");
                          /*if(getUserName(bid) instanceof String){
     System.out.println(Integer.parseInt(getUserName(bid))+111);
    }*/ 
    rows=pstmt.executeUpdate();
    if(rows==1){
     chu.search();
    }
   } catch (SQLException e) {
    e.printStackTrace();
   }finally{
    dbHandler.getClose(rs, pstmt, conn);
   }
  }
 /*//不带参数,但是使用了事务
 public static int updateing1(){
  Connection conn=dbHandler.getConnection();
  int count=0;
  String[] sqls={
    "update book set name='十万个为什么' where id=1004",
    "update book set DESCRIPTION='这里是描述' where id=1002",
    "update book set DESCRIPTION='这里是描述' where id=1002"
  };
  try {
   conn.setAutoCommit(false);
   stmt=conn.createStatement();
   for(int i=0;i<sqls.length;i++){
    stmt.executeUpdate(sqls[i]);
    count++;
   }
   conn.commit();   
  } catch (SQLException e) {
   try {
    conn.rollback();
    count=0;
    System.out.println("回滚");
   } catch (SQLException e1) {
    e1.printStackTrace();
   }
   System.out.println("异常");
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  }
  return count;
 }*/
 
 /*//不带参数,但是使用了事务,现在用这个方法做作业
 public static int updateing2(){
  Connection conn=dbHandler.getConnection();
  int count=0;
  String[] sqls={
    "update book set name='struts2实战经典?!!' where id=1001",    
    "select * from book where id=1002",
    "update book set description='重写描述与一下111' where id=1002",
  };
  try {
   conn.setAutoCommit(false);//开启事务
   stmt=conn.createStatement();
   for(int i=0;i<sqls.length;i++){
    Boolean b=stmt.execute(sqls[i]);//执行,用execute
    //System.out.println("111111111"+b);
    count++;
    if(count==sqls.length){//如果都执行过
     chu.search();//调用查询全部这个函数
    }
   }
   conn.commit(); //提交  
  } catch (SQLException e) {
   try {
    conn.rollback();//回滚
    count=0;
   } catch (SQLException e1) {
    e1.printStackTrace();
   }
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  } 
  return count;
 }*/
 
 //使用了事务,使用了问号,没用executeBatch(批处理),跟executeBatch一样的效果
 public static int updateing3(){
  Connection conn=dbHandler.getConnection();
  int count=0;
  String sql="insert into book values(?,?,?)";
  try {
   conn.setAutoCommit(false);//开启事务
   pstmt=conn.prepareStatement(sql);
   for(int i=1;i<=3;i++){
    pstmt.setInt(1, 10+i);
    pstmt.setString(2, "这是书名"+i);
    pstmt.setString(3, "这是描述"+i);
    pstmt.executeUpdate();
    count++;
   }
   conn.commit(); //提交  
  } catch (SQLException e) {
   try {
    conn.rollback();//回滚
    count=0;
   } catch (SQLException e1) {
    e1.printStackTrace();
   }
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  } 
  return count;
 }
 
 
 //查询,当修改成功之后调用这个方法
 public static void search(){
  Connection conn=dbHandler.getConnection();
  String sql="select * from book";
  try {
   Statement stmt=conn.createStatement();
   ResultSet rs=stmt.executeQuery(sql);
   ResultSetMetaData md = rs.getMetaData();
   int colsCount = md.getColumnCount();
   while(rs.next()){
    for(int i=1;i<=colsCount;i++){
     System.out.print(rs.getObject(i)+"  ");
    }
    System.out.println();
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  }
 }
 public static String getUserName(int bid){
  String u=null;
  Connection conn=dbHandler.getConnection();
  //String sql="select * from book"+" where id="+bid;
  String sql="select * from book"+" where id="+bid;
  try {
   Statement stmt=conn.createStatement();
   ResultSet rs=stmt.executeQuery(sql);
   rs.next();
    u=rs.getString("name");
   //System.out.println("成功");
  } catch (SQLException e) {
   e.printStackTrace();
  }
  /*finally{
   dbHandler.getClose(rs, pstmt, conn);
  }*/
  return u;
 }
 public static void main(String[] args) { 
  //updateing();
  updateing1(1002);
  /*int n=updateing1();
  System.out.println("执行条数"+n);*/
  //search();
  //int n=updateing2(); 
  //updateing3();
  //getUserName(1002);
 }
}
 
第三:第一种分页查询:利用滚动结果集进行分页查询
package updateTest;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import comm.dbHandler;
//利用滚动结果集进行分页查询
public class TestBufferPage {
 public static void getPage(int page,int pagesize){
  Statement stmt=null;
  ResultSet rs=null;
  int begin=(page-1)*pagesize+1;//每页的起始行数,这个很重要
  Connection conn=dbHandler.getConnection();
  String sql="select * from cou";
   try {
    //createStatement默认情况下是只进只读,现在加了参数,让他变成了滚动,只读
   stmt=conn.createStatement
   (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);//滚动,只读
   rs=stmt.executeQuery(sql);
   rs.absolute(begin);//绝对定位到这一页的begin位置,也就是这一页的第一行
   for(int i=1;i<=pagesize;i++){
    //System.out.println("成功");
    System.out.println(rs.getString("cid")+" "+rs.getString("cname")+" "+rs.getInt("xf"));
    if(!rs.next()){//rs表示这一行,这句话是说这一行没数据的时候就退出。在最后一次,如果数据不够pagesize,当没有数据的时候就退出
     break;
    }
   }
   
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, stmt, conn);
  }
 }
 public static void main(String[] args) {
  getPage(5,4);
 }
}
 
第四:第二种分页查询:利用复杂select语句进行分页查询
package updateTest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import comm.dbHandler;
//复杂select语句分页
public class 分页2 {
 public static void page(int page,int pagesize){
  String sql="select cid,cname,xf from cou";
  String sql1="select cid,cname,xf from cou order by cid desc ";//1.这是将这个表降序
  String sql2="select rownum rn,cid,cname,xf from(select cid,cname,xf from cou order by cid desc)";//2.根据1的结果写出行号,rownum这是系统给的用来记录行号的
  //3.在2的基础上,加上where条件,两个问号分别是两个参数。
  String sql3="select cid,cname,xf from " +
    "(select rownum rn,cid,cname,xf from " +
    "(select cid,cname,xf from cou order by cid desc)) " +
    "where rn between ? and ?";
  
  
  Connection conn=dbHandler.getConnection();
  PreparedStatement pstmt = null;
  ResultSet rs=null;
  int begin=(page-1)*pagesize+1;//起始行
  int end=begin+pagesize-1;//结束行
  try {
   pstmt=conn.prepareStatement(sql3);
   pstmt.setInt(1, begin);
   pstmt.setInt(2, end);
   rs=pstmt.executeQuery();
   while(rs.next()){
    System.out.println(rs.getString("cid")+" "+rs.getString("cname")+" "+rs.getInt("xf"));
                if(!rs.next()){
                 break;
                }
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   dbHandler.getClose(rs, pstmt, conn);
  }
 }
 public static void main(String[] args) {
  page(1,6);
 }
}

 
分享到:
评论

相关推荐

    1-JSP+JDBC_假分页.rar

    本案例重点阐述了J2EE中分页代码的基本实现原理,通过假分页展示分页代码的开发,本章作为分页代码的一个开始单元,为后续代码的基础。 产品:JDK 1.5、Tomcat 5.0、MySQL数据库 技术:JAVA、JSP内置对象、SQL...

    J2EE JNDI配置原理详解 JBOSS安装配置 Maven入门 Ant使用入门

    1.4 JavaBean中使用JDBC方式进行事务处理 1.5 JSP 隐式对象简介 1.6 Java解析XML的四种方法 1.7 struts1和truts2比较 1.8 Tomcat5启动流程与配置详解 1.9 HttpServlet详解 1.10 Ant使用入门 1.11 Maven Ant...

    MLDN-J2EE核心教程

    本案例重点阐述了J2EE中分页代码的基本实现原理,通过真分页,讲解数据库分页的基本原理,之后为了读者以后的开发方便,将分页程序进行抽象,抽象为一种灵活的分页组件。 产品:JDK 1.5、Tomcat 5.0、MySQL数据库 ...

    J2EE实验指导书*******

    ④配置项目构建路径添加SQL Server的JDBC驱动程序 14 2、JDBC实现CRUD操作 14 四、实验报告 15 实验三 JDBC进阶 16 一、实验目的 16 二、实验环境 16 三、实验步骤 16 1、在Eclispe中创建Java项目并编写DBConnection...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    由于J2EE的开源的框架中提供了MVC模式实现框架Struts、对象关系模型中的Hibernate 的框架及拥有事务管理和依赖注入的Spring。利用现存框架可以更快开发系统。所以选择Java技术作为blog 的开发工具。 为了增加系统的...

    基于原生JavaWeb的书店商城系统源码+数据库+安装使用说明,适用初学者

    基于原生JavaWeb的书店商城系统源码+数据库+安装使用说明。适合初学者。...前端:JSP+JQuery,后端:J2EE+... 根据bookDB.sql文件生成数据库,并配置jdbc.properties数据源 配置项目结构(web、lib依赖),添加Tomcat运行

    springmybatis

    MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm...

    Hibernate教程

    策略:事务缓存(transactional) 20.3. 管理缓存(Managing the caches) 20.4. 查询缓存(The Query Cache) 20.5. 理解集合性能(Understanding Collection performance) 20.5.1. 分类(Taxonomy) 20.5.2....

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     17.1.11 可滚动的结果集  17.1.12 在HQL查询语句中绑定参数  17.1.13 设置查询附属事项  17.1.14 在映射文件中定义命名查询语句  17.1.15 在HQL查询语句中调用函数  17.2 设定查询条件  17.2.1 比较运算  ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     17.1.11 可滚动的结果集  17.1.12 在HQL查询语句中绑定参数  17.1.13 设置查询附属事项  17.1.14 在映射文件中定义命名查询语句  17.1.15 在HQL查询语句中调用函数  17.2 设定查询条件  17.2.1 比较运算  ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     17.1.11 可滚动的结果集  17.1.12 在HQL查询语句中绑定参数  17.1.13 设置查询附属事项  17.1.14 在映射文件中定义命名查询语句  17.1.15 在HQL查询语句中调用函数  17.2 设定查询条件  17.2.1 比较运算  ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     17.1.11 可滚动的结果集  17.1.12 在HQL查询语句中绑定参数  17.1.13 设置查询附属事项  17.1.14 在映射文件中定义命名查询语句  17.1.15 在HQL查询语句中调用函数  17.2 设定查询条件  17.2.1 比较运算  ...

    Hibernate参考文档

    策略:事务缓存(transactional) 19.3. 管理缓存(Managing the caches) 19.4. 查询缓存(The Query Cache) 19.5. 理解集合性能(Understanding Collection performance) 19.5.1. 分类(Taxonomy) 19.5.2....

    hibernate 框架详解

    限制结果集内容 16.3. 结果集排序 16.4. 关联 16.5. 动态关联抓取 16.6. 查询示例 16.7. 投影(Projections)、聚合(aggregation)和分组(grouping) 16.8. 离线(detached)查询和子查询 17. Native SQL查询 ...

    最全Hibernate 参考文档

    策略:事务缓存(transactional) 19.3. 管理缓存(Managing the caches) 19.4. 查询缓存(The Query Cache) 19.5. 理解集合性能(Understanding Collection performance) 19.5.1. 分类(Taxonomy) 19.5.2....

    Hibernate 中文 html 帮助文档

    策略:事务缓存(transactional) 19.3. 管理缓存(Managing the caches) 19.4. 查询缓存(The Query Cache) 19.5. 理解集合性能(Understanding Collection performance) 19.5.1. 分类(Taxonomy) 19.5.2....

    Spring面试题

    使用 AOP 后,公共服务 (比如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。 IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。...

    hibernate 体系结构与配置 参考文档(html)

    限制结果集内容 15.3. 结果集排序 15.4. 关联 15.5. 动态关联抓取 15.6. 查询示例 15.7. 投影(Projections)、聚合(aggregation)和分组(grouping) 15.8. 离线(detached)查询和子查询 15.9. 根据自然标识...

    Hibernate3+中文参考文档

    策略:事务缓存(transactional) 19.3. 管理缓存(Managing the caches) 19.4. 查询缓存(The Query Cache) 19.5. 理解集合性能(Understanding Collection performance) 19.5.1. 分类(Taxonomy) 19.5.2....

    hibernate3.04中文文档.chm

    策略:事务缓存(transactional) 20.3. 管理缓存(Managing the caches) 20.4. 查询缓存(The Query Cache) 20.5. 理解集合性能(Understanding Collection performance) 20.5.1. 分类(Taxonomy) ...

Global site tag (gtag.js) - Google Analytics