JavaWeb 后端 <九> 之 JDBC加强

一、大结果集的分页(重点,难点)

1、分批次查询:分页

2、基于数据库的分页:依赖的是数据库的分页语句(不同数据库是不同的)

MySQL:每页显示10条。

 

select * from XXX limit M,N;

M:开始记录的索引。第一条记录的索引为0.

N:一次查询几条记录。

 

第一页:select * from CUSTOMERS limit 0,10;

第二页:select * from CUSTOMERS limit 10,10;

 ......

第n页:select * from CUSTOMERs limit (n-1)*10,10;

 

总页数:

select count(*) from customers %10==0?select count(*) from customers /10:select count(*) from customers /10+1;

二、批处理:batch(练一遍)

<strong><span style="color: #ff0000;">降低与数据库的交互次数,提升执行效率</span></strong>

public class BatchDemo {
     
    /*
     create database day16;
     use day16;
     create table t1(
        id int primary key,
        name varchar(100)
     );
     */
     
    //向数据库中插入2条记录,再把第一条删除掉
    //Statement可以批处理语句不同的。
    @Test
    public void test1() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        Statement stmt = conn.createStatement();
        String sql1 = "insert into t1 values(1,'aaa1')";
        String sql2 = "insert into t1 values(2,'aaa2')";
        String sql3 = "delete from t1 where id=1";
        stmt.addBatch(sql1);//Statement实例内部有一个List,sql语句加到List中了
        stmt.addBatch(sql2);
        stmt.addBatch(sql3);
         
        int[] ii = stmt.executeBatch();//返回值是一个数组,数组的元素为每条语句影响到的行数
        for(int i:ii)
            System.out.println(i);
         
        JdbcUtil.release(null, stmt, conn);
         
    }
      
    //插入10条记录。PreparedStatement 适合语句相同,只是参数不通的情况
    @Test
    public void test2() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("insert into t1 values (?,?)");
        for(int i=0;i<10;i++){
            stmt.setInt(1, i+1);
            stmt.setString(2, "aaaa"+(i+1));
            stmt.addBatch();
        }
         
        stmt.executeBatch();
        JdbcUtil.release(null, stmt, conn);
    }
     
    //插入1000001条记录。PreparedStatement 适合语句相同,只是参数不通的情况
    @Test
    public void test3() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("insert into t1 values (?,?)");
        for(int i=0;i<1000001;i++){
            stmt.setInt(1, i+1);
            stmt.setString(2, "aaaa"+(i+1));
            stmt.addBatch();
            if(i%1000==0){
                stmt.executeBatch();
                stmt.clearBatch();//清理缓存
            }
        }
         
        stmt.executeBatch();
        JdbcUtil.release(null, stmt, conn);
    }
}

三、Clob、Blob的读写(练一遍):文件上传

LOB:Large Object

Clob:Character Large Object字符(小说)

Blob:Binary Large Object二进制

//大数据的存取
public class LobDemo {
    /*
     create table t2(
        id int,
        content longtext
     );
     */
    @Test
    public void test1() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("insert into t2 values (?,?)");
        stmt.setInt(1, 1);
        //以流的方式
        File file = new File("src/jpm.txt");
        Reader reader = new FileReader(file);
        stmt.setCharacterStream(2, reader, (int)file.length());//PreparedStatement的实现是由数据库驱动提供的
                                                            //MySQL:setCharacterStream(int,Reader,long);根本没有实现。
                                                            //MySQL根本不支持那么大的数据。
        stmt.executeUpdate();
        JdbcUtil.release(null, stmt, conn);
    }
     
    //取大文本数据
    @Test
    public void test2() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("select * from t2 where id=1");
        ResultSet rs = stmt.executeQuery();
        if(rs.next()){
            Reader r = rs.getCharacterStream("content");
            //内容保存D盘的1.txt文件中
            Writer w = new FileWriter("d:/1.txt");
            int len = -1;
            char c[] = new char[1024];
            while((len=r.read(c))!=-1){
                w.write(new String(c), 0, len);
            }
            r.close();
            w.close();
        }
        JdbcUtil.release(rs, stmt, conn);
    }
     
    /*
     create table t3(
        id int,
        content longblob
     );
     */
    @Test
    public void test3() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("insert into t3 values (?,?)");
        stmt.setInt(1, 1);
        //以流的方式
        InputStream in = new FileInputStream("src/26.jpg");
         
        stmt.setBinaryStream(2, in, in.available());
        stmt.executeUpdate();
        JdbcUtil.release(null, stmt, conn);
    }
    @Test
    public void test4() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement stmt = conn.prepareStatement("select * from t3 where id=1");
        ResultSet rs = stmt.executeQuery();
        if(rs.next()){
            InputStream in = rs.getBinaryStream("content");
            OutputStream out = new FileOutputStream("d:/wife.jpg");
             
            int len = -1;
            byte b[] = new byte[1024];
            while((len=in.read(b))!=-1){
                out.write(b,0,len);
            }
            in.close();
            out.close();
        }
        JdbcUtil.release(null, stmt, conn);
    }
}

四、如何调用存储过程

 

/*
delimiter $$
 
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam varchar(255))
BEGIN
    SELECT CONCAT('zyxw---', inputParam) into inOutParam;
END $$
 
delimiter ;
 */
 
//如何调用已经存在的存储过程
public class CallableDemo {
    @Test
    public void test1() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        CallableStatement stmt = conn.prepareCall("{call demoSp(?,?)}");
        //输入参数:设置值
        //输出参数:注册数据类型即可
        stmt.setString(1, "YY");
        stmt.registerOutParameter(2, Types.VARCHAR);
         
        stmt.execute();
        //打印执行的结果
        System.out.println(stmt.getString(2));
        JdbcUtil.release(null, stmt, conn);
    }
}

五、事务入门(重点)

1、MySQL:每一条语句都属于独立事务,默认自动管理的。

2、开启事务:start transaction;   日后的语句都会处于同一个事务之中。

提交事务:commit;

回滚事务:rollback;

3、JDBC如何控制事务

//事务控制案例
/*
 
 
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money float
)character set utf8 collate utf8_general_ci;
 
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
 
 */
public class TxDemo {
    @Test
    public void test1(){
        Connection conn = null;
        PreparedStatement stmt = null;
        try{
            conn = JdbcUtil.getConnection();
            conn.setAutoCommit(false);//相当于start transaction
             
            stmt = conn.prepareStatement("update account set money=money-100 where name='bbb'");
            stmt.executeUpdate();
             
//          int i=1/0;
             
            stmt = conn.prepareStatement("update account set money=money+100 where name='aaa'");
            stmt.executeUpdate();
             
            conn.commit();// 提交事务
        }catch(Exception e){
//          if(conn!=null){
//              try {
//                  conn.rollback();
//              } catch (SQLException e1) {
//                  e1.printStackTrace();
//              }
//          }
            throw new RuntimeException(e);
        }finally{
            JdbcUtil.release(null, stmt, conn);
        }
    }
}

六、事务的特性(重点。面试)

1、事务的特性:

原子性:处于事务中的多条语句是不可分割的。

一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如:转账,转账前A+B=2000,转账后A+B=2000

隔离性:多线程并发。一个事务不能被其他线程中的事务所打扰。

持久性:事务一旦提交,永久保存起来。

2、事务的隔离级别:属于事务的。都已开启了事务为前提。

不考虑事务的隔离级别,会出现以下情况(是错的)

l  脏读:一个线程中的事务读到了另外一个线程中未提交的数据。

l  不可重复读:一个线程中的事务读到了另外一个线程中已经提交的update的数据。

l  虚读:一个线程中的事务读到了另外一个线程中已经提交的insert的数据。

 

要想避免以上现象,通过更改事务的隔离级别来避免:

l  READ UNCOMMITTED 脏读、不可重复读、虚读有可能发生。

l  READ COMMITTED 避免脏读的发生,不可重复读、虚读有可能发生。

l  REPEATABLE READ 避免脏读、不可重复读的发生,虚读有可能发生。

l  SERIALIZABLE 避免脏读、不可重复读、虚读的发生。

 

级别依次升高,效率依次降低。

MySQL:默认REPEATABLE READ

ORACLE:默认READ COMMITTED

 

MySQL:

select @@tx_isolation;//查看当前的隔离级别

set transaction isolation level 级别;// 设置当前的事务隔离级别

 

 

练习:read uncommitted;


时间


T1


T2


说明


t1


start transaction


 


 


t2


select * from account where name='aaa';

有1000块


 


 


t3


 


start transaction


 


t4


 


update account set money=money+100 where name='aaa';


 


t5


select * from account where name='aaa';

有1100块


 


读到了另外一个线程中未提交的数据:脏读


t6


 


commit;


 


t7


select * from account where name='aaa';

有1100块


 


读到了另外一个线程中提交的update数据:不可重复读


t8


select count(*) from account;

有3条记录


 


 


t9


 


insert into account values(4,'ddd',1000);


 


t10


select count(*) from account;

有4条记录


 


读到了另外一个线程中提交的insert数据:虚读(幻读)


t11


commit;


 


 


 


 


 


 

//设置隔离级别
public class IsolationLevelDemo {
    @Test
    public void test1() throws Exception{
        Connection conn = JdbcUtil.getConnection();
        //一定要在开启事务前更改隔离级别
        conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
        conn.setAutoCommit(false);
         
//      ....
        conn.commit();
    }
}
时间: 2024-11-05 20:42:19

JavaWeb 后端 <九> 之 JDBC加强的相关文章

JavaWeb 后端 &lt;八&gt; 之 JDBC基礎(全)

一.JDBC简介 1.JDBC是SUN公司为了简化操作数据推出一套规范.数据库厂商的驱动就是对JDBC的实现. 2.Java Data Base Connectivity(java数据库连接),它主要由接口组成. java.sql.*    javax.sql.*   JDK中 数据库的驱动jar包 (mysql-connector-java-5.0.8-bin.jar ) 二.JDBC的编码步骤 0.前提:拷贝数据库的驱动到构建路径中(classpath) 1.注册驱动 2.获取与数据库的链接

JavaWeb 后端 &lt;一&gt; 之 Tomcat服务器 - Http协议 学习笔记

1.Web开发概述 1.1服务器上的资源分类: a.静态资源:指web页面中供人们浏览的数据始终是不变.html css js 图片 多媒体 b.动态资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同.JSP/Servlet.php.asp 下面为简单的java程序 模拟服务器提供资源 访问 本地端口1111即可得到服务器的资源 public class Myserver {     public static void main(String[] a

JavaWeb 后端 &lt;四&gt; 之 Cookie HttpSession 学习笔记

一.会话管理概述 1.什么是会话? 好比一次通话.打开浏览器,点击多次链接(发出多次请求和收到多次的响应),关闭浏览器,这个过程就是一次会话. 有功能 可以  文件 新建会话   2.解决的问题是什么? 共享多次请求中产生的数据.比如购物车. 二.客户端技术:Cookie 0.HTTP协议的消息头 请求消息头:Cookie 客户端向服务器端传递信息 响应消息头:Set-Cookie 服务器端向客户端传递信息 1.Cookie详解: l  属性: name:Cookie的名称,必要的属性 valu

JavaWeb 后端 &lt;五&gt; 之 JSP 学习笔记

一.JSP简介 1.也是SUN公司推出的开发动态web资源的技术,属于JavaEE技术之一.由于原理上是Servlet, 所以JSP/Servlet在一起. 二.HTML.Servlet和JSP 1.HTML:静态页面,不能包含java代码,只能有HTML有关的标记 2.Servlet:写java代码,做页面的输出,不是很方便(开发效率很低) 3.JSP:HTML+java 三.输出当前的时间 <%@ page language="java" import="java.

MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)

[正文] 首先需要回顾一下上一篇文章中的内容:MySQL数据库学习笔记(八)----JDBC入门及简单增删改数据库的操作 一.ResultSet接口的介绍: 对数据库的查询操作,一般需要返回查询结果,在程序中,JDBC为我们提供了ResultSet接口来专门处理查询结果集. Statement通过以下方法执行一个查询操作: ResultSet executeQuery(String sql) throws SQLException  单词Query就是查询的意思.函数的返回类型是ResultSe

JavaWeb 后端 &lt;十一&gt; 之 DBUtils 框架 (基本使用 结果集 事务处理 对表读取)

一.数据库操作框架 1.ORM:Object Relation Mapping Hibernate:非常流行 JPA:Java Persistent API.ORM标准 MyBatis:2010年开始.之前叫做iBatis(重视) 2.JDBC封装框架 DBUtils Spring JDBC Template 二.Apache的DBUtils框架(会用:练习作业) 1.基本的使用 DBCPutil public class DBCPUtil {     private static DataSo

JavaWeb 后端 &lt;二&gt; 之 Servlet 学习笔记

 一.Servlet概述 1.什么是Servlet Servlet是一个运行在服务器端的Java小程序,通过HTTP协议用于接收来自客户端请求,并发出响应. 2.Servlet中的方法 public void service(ServletRequest req,ServletResponse res) throws ServletException,java.io.IOException   ServletRequest req:代表着请求对象,该对象中有HTTP协议的请求部分的所有内容.它的

JavaWeb 后端 &lt;十三&gt; 之 监听器 JSTL国际化

1. 监听器 1.1   概述 监听器: 主要是用来监听特定对象的创建或销毁.属性的变化的!                     是一个实现特定接口的普通java类! 对象:          自己创建自己用 (不用监听)          别人创建自己用 (需要监听)   Servlet中哪些对象需要监听?          request / session / servletContext          分别对应的是request监听器.session相关监听器.servletCo

JavaWeb 后端 &lt;十&gt; 之 数据池 C3P0 DPCB JNDI

一.数据库连接池原理:(理解) //模拟数据库连接池的原理 public class ConnectionPoolDemo {     private static List<Connection> pool = new ArrayList<Connection>();     static{         try {             for(int i=0;i<10;i++){                 Connection conn = JdbcUtil.