`

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);
 }
}

 
分享到:
评论

相关推荐

    J2EE登陆和分页

    对于分页,可以设计一个`Pagination`类,包含当前页、总页数、每页条数等属性,以及用于构造分页SQL的方法。 总的来说,理解和熟练掌握J2EE中的用户登陆和分页机制是开发高效、安全的企业级应用的基础。通过对JDBC...

    jdbc+jsp分页组件+源代码

    JDBC的主要功能包括连接数据库、执行SQL语句、处理结果集等。在JDBC中,我们通常需要经历以下几个步骤:加载驱动、建立连接、创建Statement或PreparedStatement对象、执行SQL语句、处理结果集、关闭连接。 2. JSP...

    Servlet+JSP+JDBC实现增删查(真分页)改j2ee小项目

    在本项目中,"Servlet+JSP+JDBC实现增删查(真分页)改j2ee小项目"是一个基于Java技术栈的Web应用程序,主要用于演示如何在J2EE环境中进行数据操作,包括添加、删除、查询和更新功能,并且实现了真正的分页功能。...

    纯JSP +JDBC实现分页

    通过JDBC,我们可以连接到数据库,执行SQL语句,获取结果集并进行处理。使用JDBC进行分页查询,通常需要编写SQL的LIMIT或OFFSET子句,以获取特定范围的数据。 分页的核心在于如何有效地获取和展示数据库中的数据...

    session,sql分页

    在J2EE应用程序开发中,`session`和`SQL分页`是两个非常重要的概念,尤其是在处理用户交互和大量数据时。本文将深入探讨这两个主题,并结合SQL Server数据库的使用来阐述它们在实际开发中的应用。 首先,让我们来...

    j2ee框架笔记详细介绍j2ee的框架结构

    这种方法简单,但当数据集变化时,结果可能不准确。 2. **真分页**:真分页则涉及到数据库层面的分页,如在Oracle数据库中,可以使用ROWNUM或ROWNUMBER()函数配合查询条件实现精确的分页。这种方法性能较低,因为它...

    j2ee学校查询系统,有管理员,教师,学生分页

    【标题】"j2EE学校查询系统,有管理员,教师,学生分页"是一个基于Java企业版(J2EE)技术构建的教育信息化应用。它主要用于实现学校信息的查询功能,同时提供了不同角色(管理员、教师和学生)的权限管理,并具备...

    与JDBC兼容性的分页

    由于JDBC 1.0版本中的`ResultSet`接口只能通过`next()`方法进行单向遍历,且一次只能执行一条SQL语句,无法控制返回结果集的大小,因此在JDBC 1.0下实现分页变得十分困难。尽管JDBC 2.0之后引入了更多特性,如双向...

    j2ee+ssi模糊查询

    - **处理结果集**:查询结果将返回一个`ResultSet`对象,可以遍历这个集合,将数据展示在JSP页面上。 2. **SSI在模糊查询中的应用**: - **SSI插入动态内容**:虽然JSP本身已经具备了动态内容的能力,但有时为了...

    J2EE经典教程

    它基于Java SE,并在此基础上增加了许多针对大型分布式网络应用的技术和服务支持,例如:容器管理、事务处理、安全性、持久化等。J2EE的核心目标是提供一套完整的解决方案来构建和部署可移植、健壮、可伸缩且安全的...

    山东建筑大学J2EE讲义

    JDBC支持事务处理,通过`Connection`对象的`setAutoCommit(false)`方法可以开启事务模式。 #### 四、Servlet基础 **4.1 Servlet概述** - **4.1.1 Servlet的概念**:Servlet是Java EE的一个关键技术,它是一个Java...

    java之jdbc总结

    7. **处理结果集**:通过`ResultSet`对象遍历查询结果,通常使用`while(rs.next())`循环。 8. **释放资源**:为了防止资源泄漏,必须按照`ResultSet -&gt; Statement -&gt; Connection`的顺序关闭它们,通常在`finally`块...

    J2EE.zip_jsp+j2ee

    J2EE的核心在于其组件模型,包括EJB(Enterprise JavaBeans)、Servlet和JSP(JavaServer Pages)等,这些组件可以在服务器端运行,处理复杂的业务逻辑,并与客户端进行交互。 **二、SSH框架** SSH 框架是指 Struts...

    J2EE电子商务系统开发从入门到精通:基于Struts和Hibernate技术实现

    - **分页显示的实现**:通过SQL查询或Hibernate API实现数据分页。 #### 企业在线信息系统网站概述与架构设计 - **概述**: - 该网站旨在为企业的日常运营提供一个综合的信息管理系统。 - 包括员工登录、人事...

    J2EE学生管理demo

    【J2EE学生管理demo】是一个基于Java企业版(J2EE)技术的简单示例应用,用于展示如何实现对学生信息的管理。J2EE是Java平台的企业版本,它为开发和部署分布式、多层的企业应用程序提供了框架和组件。在这个demo中,...

    dao层增删改查分页查找

    本话题将深入探讨如何在DAO层利用J2EE技术进行这些基本操作,并引入分页查找功能。 首先,让我们了解DAO设计模式。DAO模式是软件设计模式之一,它的主要作用是为业务逻辑层提供一个接口,用来访问和操作数据源,...

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

    《J2EE实验指导书》是一份详细的教程,旨在帮助学习者熟悉J2EE编程环境,掌握JDBC、Servlet、JSP、JavaBean等核心技术,并通过一系列实验实践提高开发技能。以下是各实验的关键知识点: 实验一 熟悉J2EE编程环境: ...

    J2EE电子商务系统开发

    - **分页显示的实现**:通过SQL查询或Hibernate API实现对结果集的分页。 #### 四、企业在线信息系统网站概述与架构设计 - **企业在线综合信息管理网站概述** - **设计与实现**:采用分层架构,确保各层职责明确...

    jsp分页(基于mssql数据库)

    3. **构建分页SQL**:根据当前页码调整`OFFSET`和`FETCH NEXT`的值,生成分页SQL。 4. **执行SQL并获取数据**:使用JDBC执行SQL,获取当前页的数据。 5. **渲染分页导航**:在JSP页面上显示分页链接,通常包括“上...

Global site tag (gtag.js) - Google Analytics