JDBC学习笔记

总结 JDBC知识点
* 什么是JDBC
标准,接口,驱动程序
* JDBC编码步骤TCP协议
* 一组接口
DriverManager
Connection
Statement
PreparedStatement
ResultSet
* 语句对象
Statement
PreparedStatement
CallableStatement: 可以调用存储过程
* 几个JDBC知识点
*事务处理
*批量处理
*可滚动处理集
*数据库端分页JDBC实现
-------------------------------------------------------------

 

 

 

01
================================================================
1.JDBC的编码步骤
1) 加载数据库驱动
驱动程序:即是JDBC这组接口的实现类和其他功能类
由数据库厂商提供

导入mysql jar包

2) 创建连接
DriverManager 驱动管理器
DriverManager提供一个静态方法,建立与数据库的连接
getConnection(url,user,pwd)
url:连接数据库地址
jdbc:mysql://ip:3306/数据库名

jdbc:主协议
mysql:子协议
ip:远程其他机器,就是具体的ip
本机127.0.0.1或localhost

3) 发送sql语句并执行

Statement stmt = connection.createStatement();
statement 表示语句对象
int executeUpdate(String sql)
用来发送insert update delete语句

ResultSet executeQuery(String sql)
用来发送select语句,返回结果集

4) 关闭连接
数据库软件同时支持的连接数是有限的,每一个连接都占有着数据库有限的资源,开启连接程序执行结束后
必须及时释放资源,关闭连接
close():关闭语句对象,关闭连接对象

API:
DriverManager:类.驱动管理器
Connection getConnecrion(url,user,pwd);
Connection:连接对象的接口
Statement createStatement();
Statement:语句对象的接口
int executeUpdate(String sql);
发送增删改查sql语句
ResultSet executeQuery(String sql);
发送查询sql语句

2. *加载驱动
*创建连接
*发送sql语句
*处理结果集(如果是查询)
*关闭连接

ResultSet:结果集对象,带有指针的一块内存区域
boolean next();移动结果集指针,默认指针指向第一条记录之前,next()指向第一条记录,
如果有记录,返回true,否则返回false
getXXX(String columnName);获取字段值





02
======================================================================================
PreparedStatement 预处理语句对象
是Statement的子接口
* 避免sql注入
* 提高多次执行同一条sql语句的效率(缓存)
* sql 语句的可读性更好
只要sql中需要拼接java变量,就使用PreparedStatement

sql语句--->预编译---->执行计划

 

PreparedStatement接口的使用:
* sql语句中有java变量用?替代 ?作为占位符
select * from user where username = ? and password = ?
* 实例化
实例化期间传sql
PreparedStatement pstmt = conn.prepareStatement(sql);

* 装配占位符?的值
pstmt.setString(1,username);
pstmt.setString(2,password);

* 执行sql语句
执行查询
pstmt.excuteQuery();
发送执行增删改查语句
pstmt.excuteUpdate();


------------------------
******解析配置文件
1.获取指向类路径属性文件的输入流
InputStream in = 当前类.class.getClassLoader().getResourceAsStream("db.properties");
prop.load(in);
根据key取值
String url = prop.getProperty("url");

*****
2.还可以用java.util.ResourceBundle解析加载配置文件
ResourceBundle bundle = ResourceBundle.getBundle("db");
String url = bundle.getString("url");

----------------------------------------------------
*******连接池
* 提高效率
不需要对应所有请求,临时创建新的连接
* 可以管理连接数

*成熟的连接池组件
DBCP(DataBase Connection Pool) 核心类(BasicDataSource)
BasicDataSource dataSource = new BasicDataSource();

        //加载参数
        dataSource = new BasicDataSource();
        //读取数据
        ResourceBundle bundle = ResourceBundle.getBundle("db");
        String url = bundle.getString("jdbc.url");
        String username = bundle.getString("jdbc.username");
        String password = bundle.getString("jdbc.password");
        
        int initsize = Integer.parseInt(bundle.getString("jdbc.initialSize"));
        int maxactive = Integer.parseInt(bundle.getString("jdbc.maxActive"));
        int maxwait = Integer.parseInt(bundle.getString("jdbc.maxWait"));
        
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        
        //设置初始化连接数
        dataSource.setInitialSize(initsize);
        //设置最大连接数
        dataSource.setMaxActive(maxactive);
        //设置最大等待时间
        dataSource.setMaxWait(maxwait);

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
jdbc.initialSize=20
jdbc.maxActive=100
jdbc.maxWait=5000

 


c3p0(不需要写代码读取配置文件,直接配置c3p0-config.xml就好了)
DataSource dataSource = new ComboPooledDataSource("c3p0");

 

//加载参数
        dataSource = new ComboPooledDataSource("c3p0");

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>

  <named-config name="c3p0"> 

      <property name="user">root</property>

      <property name="password">root</property>

      <property name="driverClass">com.mysql.jdbc.Driver</property>

      <property name="jdbcUrl">jdbc:mysql://localhost:3306/login</property>

<!--以上的user是数据库的用户,
    password是数据库的密码,driverClass是mysql的数据库驱动,jdbcUrl是连接数据库的url -->

       <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->

        <property name="acquireIncrement">5</property>

    <!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->

        <property name="initialPoolSize">10</property>

    <!--连接池中保留的最小连接数 -->

        <property name="minPoolSize">10</property>

    <!--连接池中保留的最大连接数 -->

        <property name="maxPoolSize">50</property>

    <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->

        <property name="maxStatements">20</property> 

    <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->

        <property name="maxStatementsPerConnection">5</property>

      </named-config>

</c3p0-config>

 

------------------------------------------------------
JDBC中的事务处理
事务:                 

  一组操作的逻辑单元
  一组添加         一组删除    一组更新
事务具备四个特性(ACID)
  ----原子性(atomicity):

        一个事务是一个不可分割的逻辑单元,一个事务中,所有操作要么成功要么失败(转账业务,一个减少一个增加金额)
  ----一致性(Consistency):

        事务执行的前后,保证数据的完整性
        完整性:完备性和正确性
        外键字段的值必须是引用其他主键字段的值
        (删除主表的数据,从表必须被修改或被删除)
  ----隔离性(Isolation):

        多个事务执行,事务之间互不干扰
        数据库软件都有默认的事务隔离级别
        隔离级别:
          串行化(serialize):多个事务操作同一个表数据,必须排队执行
          读已提交(read commited)
          读未提交
          可重复读
        李四 10000 事务没有提交
        张三 20000 脏数据
  ----持久性(Durability):

        事务一旦提交,对数据库数据的影响是永久的


***********数据库端事务的操作:


    事务开启: 执行第一条增删改sql语句,事务会自动开启
    事务结束: commit 提交事务
    rollback 回滚事务(撤销事务)

*JDBC默认自动提交事务
      ------>boolean conn.getAutoCommit();//获取先前提交方式
(批量删除)----->conn.setAutoCommit(false);//将jdbc的自动提交事务取消
       ------>conn.commit();//显示提交事务
       ------>(如果有异常)conn.rollback();//撤销事务
       ------>conn.setAutoCommit(boolean);//在连接放回连接池中之前,还原提交方式

*注意:在MySQL中,就算commit()没写也会自动提交事务,但是在oracle中必须写commit()才会提交事务

*结论:(什么时候用)当出现一组操作(多条insert,update,delete)的需求,必须关注事务

例:

String username1 = "zansan";
        String username2 = "lisi";
        double money = 10000;
        Connection conn = null;
        boolean autoCommit = false;
            try {
                conn = JDBCUtils.getConnection();
            
                //获取默认提交方式
                autoCommit = conn.getAutoCommit();
                conn.setAutoCommit(false);
                //账户一减少
                String sql = "update account set balance = balance-? where username = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setDouble(1, money);
                pstmt.setString(2, username1);
                pstmt.executeUpdate();
                //账户二增加
                String sql2 = "update account set balance = balance+? where username = ?";
                pstmt = conn.prepareStatement(sql2);
                pstmt.setDouble(1, money);
                pstmt.setString(2, username2);
                pstmt.executeUpdate();
                //提交事务
                conn.commit();
                System.out.println("转账成功");
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }finally{
                conn.setAutoCommit(autoCommit);
                JDBCUtils.close(conn);
            }

************
03
============================================================================================
1.批量处理(要加事务处理)(减少与数据库交互次数)
  *预处理语句对象PreparedStatement
  String sql = "delete from user where id = ?"
  PreparedStatement pstmt = conn.prepareStatement(sql);
如果删除十条数据,与数据库交互10次
  for(int id : ids){
    pstmt.setInt(1,id);
    //将操作添加到语句列表中
    pstmt.addBatch();
    //pstmt.executeUpdata();
    //一次性缓冲一组数据
    在语句对象中维护了一个语句列表
  }
  //一次性执行一组操作
  pstmt.executeBatch();

* addBatch(), 填充语句列表
* executeBatch(),执行语句列表

*******添加一万条数据

public static void main(String[] args){
        Connection conn = null;
        boolean autocommit = false;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "insert into account(username,balance) values(?,?)";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            autocommit = conn.getAutoCommit();
            conn.setAutoCommit(false);
            for (int i = 0; i <= 10000; i++) {
                pstmt.setString(1, "小本"+i);
                pstmt.setDouble(2, 1000+i);
                pstmt.addBatch();
                //每70个提交一次
                if(i%70==0){
                    pstmt.executeBatch();
                    //清除语句列表
                    pstmt.clearBatch();
                }
            }
            pstmt.executeBatch();
            conn.commit();
            System.out.println("执行成功");
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }finally{
            try {
                conn.setAutoCommit(autocommit);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            JDBCUtils.close(conn);
        }
        
        
    }
}

 



---------------------------------------------
2.可滚动结果集
默认结果集指针总是从前往后滚动
ResultSet rs = pstmt.executeQuery();
rs.next();

boolean next();从前往后滚
boolean absolute(int row);将结果集指针绝对定位
boolean previous();从后往前滚

---------------------------------------------
3.JDBC分页查询(Mysql)
分页
两种分页方式:
* 内存分页
查询所有数据,存储在内存中
* 数据库端分页(常用)
查询需要的数据(与数据库多次交互)
数据库(mysql)端分页:
例如每页显示3条:
查看第一页:1,2,3
查看第二页:4,5,6
查看第八页:22,23,24

limit关键字:mysql专用分页查询关键字
select id,username from user limit ?,?
int perpage = 5;
int page = 1;
int begin = (page-1)*perpage

*****分页查询

public static void main(String[] args) {
        //每页显示的记录数
        int perpage = 5;
        //当前页
        int page = 4;
        Connection conn = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select id,username,balance from account limit ?,?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, (page-1)*perpage);
            pstmt.setInt(2, perpage);
            
            ResultSet rs = pstmt.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("id")+" "+rs.getString("username")+" "+rs.getString("balance  5"));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            JDBCUtils.close(conn);
        }
        
    }

 

**************************************************************************

posted @ 2018-03-12 19:38  小奔的早晨  阅读(714)  评论(0编辑  收藏  举报