美文网首页JavaEE
JavaWeb基础恢复之操作数据库

JavaWeb基础恢复之操作数据库

作者: 平安喜乐698 | 来源:发表于2018-04-26 21:18 被阅读8次
    目录
    
    
     JDBC
        Java Data Base Connectivity(java数据库连接)
        
    
     应用
     JDBC  (位于第二层)
     各种数据库驱动
     数据库
    
    1. 使用
    下载mysql-connector-java-8.0.11.jar,并放入WEB-INF | lib下
    

    下载mysql-connector-java-8.0.11.jar , 选Platform Indepentdent

    简单使用

    1. 创建数据库、表、插入数据
    终端输入sql
    
    create database Test character set utf8 collate utf8_general_ci;
    
    use Test;
    
    create table users(
        id int primary key,
        name varchar(40),
        password varchar(40),
        email varchar(60),
        birthday date
    );
    
    insert into users(id,name,password,email,birthday) values(1,'zhansan','123456','xx@sina.com','2220-12-04');
    insert into users(id,name,password,email,birthday) values(2,'lisi','123456','xx@sina.com','2222-12-04');
    insert into users(id,name,password,email,birthday) values(3,'wangwu','123456','xx@sina.com','2222-12-04');
    

    Navicat Premium可视化工具连接本地数据库

    localhost
    3306
    root
    数据库密码
    

    2.数据库操作类

    package com.sst.cx;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    public class TestJSDBCModel {
           public static void main(String[] args) throws Exception {
    
                
                // 1.加载驱动
                /*不推荐使用这种方式来加载驱动
                  DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                    1、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。
                    2、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。
                 * */
                // 推荐使用
                Class.forName("com.mysql.jdbc.Driver"); 
                
                /* 2.1 设置 要连接的数据库URL
                 * 协议:子协议:主机:端口号/数据库名
                 * 
                    Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
                    SqlServer写法:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
                    MySql写法:jdbc:mysql://localhost:3306/sid
                 */
                String url = "jdbc:mysql://localhost:3306/数据库名";
                // 2.2 设置 连接的数据库时使用的用户名
                String username = "root";
                // 2.3 设置 连接的数据库时使用的密码
                String password = "密码";
                // 2.4 获取 与数据库的链接
                Connection conn = DriverManager.getConnection(url, username, password);
                /*
                 Connection类
                    createStatement():创建向数据库发送sql的statement对象。
                    prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。
                    prepareCall(sql):创建执行存储过程的callableStatement对象。
                    setAutoCommit(boolean autoCommit):设置事务是否自动提交。
                    commit() :在链接上提交事务。
                    rollback() :在此链接上回滚事务。
                 * */
                // 3. 获取 用于向数据库发送sql语句的statement
                Statement st = conn.createStatement();
                /*
                 Statement类
                    executeQuery(String sql) :用于向数据发送查询语句。
                    executeUpdate(String sql):用于向数据库发送insert、update或delete语句
                    execute(String sql):用于向数据库发送任意sql语句
                    addBatch(String sql) :把多条sql语句放到一个批处理中。
                    executeBatch():向数据库发送一批sql语句执行。
                 * */
                
                // -----------增-----------
                String insertSql = "insert into user(….) values(…..) "; 
                int num = st.executeUpdate(insertSql);
                if(num>0){
                    System.out.println("插入成功!!!");
                }
                
                // -----------删-----------
                String sql = "delete from user where id=1"; 
                int deleNum = st.executeUpdate(sql);
                if(deleNum>0){
                    System.out.println("删除成功!!!");
                }
                
                // -----------改-----------
                String updateSql = "update user set name='' where name=''"; 
                int updateNum = st.executeUpdate(updateSql);
                if(updateNum>0){
                    System.out.println("修改成功!!!");
                }
                
                // -----------查-----------
                String querySql = "select id,name,password,email,birthday from users";
                // 4.向数据库发sql,并获取代表结果集的resultset
                ResultSet rs = st.executeQuery(querySql);
                /*
                 ResultSet类
                    getObject(int index)
                    getObject(string columnName)
    
                    // 指定数据类型
                    getString(int index)
                    getString(String columnName)
                    。。。
    
    
                    next():移动到下一行
                    Previous():移动到前一行
                    absolute(int row):移动到指定行
                    beforeFirst():移动resultSet的最前面。
                    afterLast() :移动到resultSet的最后面。
    
                 * */
                // 5.取出结果集的数据
                while(rs.next()){
                    // 获取 字段值
                    System.out.println("id=" + rs.getObject("id"));
                    System.out.println("name=" + rs.getObject("name"));
                    System.out.println("password=" + rs.getObject("password"));
                    System.out.println("email=" + rs.getObject("email"));
                    System.out.println("birthday=" + rs.getObject("birthday"));
                }
                
                // 6.关闭链接,释放资源
                rs.close();
                st.close();
                conn.close();
            }
    }
    
    遇到的错误:java.lang.UnsupportedClassVersionError
    解决:
        换jdk版本为高版本即可
        MyEclipse|设置|Java|JRE换jdk版本
    
    
    查看jdk版本
        /usr/libexec/java_home -V
    

    规范使用

    1. 新建db.properties
    在src下新建File
    
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/Test
    username=root
    password=密码
    
    1. 新建数据库处理类
    package com.sst.cx;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    public class JdbcUtils {
    
        private static String driver = null;
        private static String url = null;
        private static String username = null;
        private static String password = null;
        
        static{
            try{
                // 读取db.properties文件中的数据库连接信息
                InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc2.properties");
    
                Properties prop = new Properties();
                prop.load(in);
                
                //获取数据库连接驱动
                driver = prop.getProperty("driver");
                //获取数据库连接URL地址
                url = prop.getProperty("url");
                //获取数据库连接用户名
                username = prop.getProperty("username");
                //获取数据库连接密码
                password = prop.getProperty("password");
                
                //加载数据库驱动
                Class.forName(driver);
                
            }catch (Exception e) {
                throw new ExceptionInInitializerError(e);
            }
        }
        
        /**
        * @Method: getConnection
        * @Description: 获取数据库连接对象
        *
        * @return Connection数据库连接对象
        * @throws SQLException
        */ 
        public static Connection getConnection() throws SQLException{
            return DriverManager.getConnection(url, username,password);
        }
        
        /**
        * @Method: release
        * @Description: 释放资源,
        *     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
        *
        * @param conn
        * @param st
        * @param rs
        */ 
        public static void release(Connection conn,Statement st,ResultSet rs){
            if(rs!=null){
                try{
                    //关闭存储查询结果的ResultSet对象
                    rs.close();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if(st!=null){
                try{
                    //关闭负责执行SQL命令的Statement对象
                    st.close();
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            if(conn!=null){
                try{
                    //关闭Connection数据库连接对象
                    conn.close();
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    3.处理类

    package com.sst.cx;
    
    import java.sql.*;
    
    public class TestJdbcM {
      
        public static void main(String[] args){
            (new TestJdbcM()).insert();
        }
        
        /*
         create database Test;
    
        use Test;
    
        create table users(
            id int primary key,
            name varchar(40),
            password varchar(40),
            email varchar(60),
            birthday date
        );
    
         * */
        // 增
        public void insert(){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try{
                //获取一个数据库连接
                conn = JdbcUtils.getConnection();
                //通过conn对象获取负责执行SQL命令的Statement对象
                st = conn.createStatement();
                //要执行的SQL命令
                String sql = "insert into users(id,name,password,email,birthday) values(6,'ss','123','xx@qq.com','2222-02-02')";
                //执行插入操作,executeUpdate方法返回成功的条数
                int num = st.executeUpdate(sql);
                if(num>0){
                    System.out.println("插入成功!!");
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally{
                //SQL执行完成之后释放相关资源
                JdbcUtils.release(conn, st, rs);
            }
        }
        
        // 删
        public void delete(){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try{
                conn = JdbcUtils.getConnection();
                String sql = "delete from users where id=3";
                st = conn.createStatement();
                int num = st.executeUpdate(sql);
                if(num>0){
                    System.out.println("删除成功!!");
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally{
                JdbcUtils.release(conn, st, rs);
            }
        }
        
        // 改
        public void update(){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try{
                conn = JdbcUtils.getConnection();
                String sql = "update users set name='hello',email='xxxx@sina.com' where id=3";
                st = conn.createStatement();
                int num = st.executeUpdate(sql);
                if(num>0){
                    System.out.println("更新成功!!");
                }
            }catch (Exception e) {
                e.printStackTrace();
                
            }finally{
                JdbcUtils.release(conn, st, rs);
            }
        }
        
        // 查
        public void find(){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try{
                conn = JdbcUtils.getConnection();
                String sql = "select * from users where id=3";
                st = conn.createStatement();
                rs = st.executeQuery(sql);
                if(rs.next()){
                    System.out.println(rs.getString("name"));
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally{
                JdbcUtils.release(conn, st, rs);
            }
        }
    }
    

    4.处理类2(占位符)

    public class JdbcCRUDByPreparedStatement {
         
    // 增     
    public void insert(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            // 获取一个数据库连接
            conn = JdbcUtils.getConnection();
            // 要执行的SQL命令,SQL中的参数使用?作为占位符
            String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
            // 通过conn对象获取负责执行SQL命令的prepareStatement对象
            st = conn.prepareStatement(sql);
            // 为SQL语句中的参数赋值,注意,索引是从1开始的
            /**
            * SQL语句中各个字段的类型如下:
            *  +----------+-------------+
            | Field    | Type        |
            +----------+-------------+
            | id       | int(11)     |
            | name     | varchar(40) |
            | password | varchar(40) |
            | email    | varchar(60) |
            | birthday | date        |
            +----------+-------------+
            */
            st.setInt(1, 1);    //    id是int类型的
            st.setString(2, "hello");//name是varchar(字符串类型)
            st.setString(3, "123");//password是varchar(字符串类型)
            st.setString(4, "xx@sina.com");//email是varchar(字符串类型)
            st.setDate(5, new java.sql.Date(new Date().getTime()));//birthday是date类型
            //执行插入操作,executeUpdate方法返回成功的条数
            int num = st.executeUpdate();
            if(num>0){
               System.out.println("插入成功!!");
            }
    
            }catch (Exception e) {
                 e.printStackTrace();
            }finally{
                 //SQL执行完成之后释放相关资源
                 JdbcUtils.release(conn, st, rs);
            }
    }
    
    
    // 删
    public void delete(){
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       try{
           conn = JdbcUtils.getConnection();
           String sql = "delete from users where id=?";
           st = conn.prepareStatement(sql);
           st.setInt(1, 1);
           int num = st.executeUpdate();
           if(num>0){
               System.out.println("删除成功!!");
           }
       }catch (Exception e) {
           e.printStackTrace();
       }finally{
           JdbcUtils.release(conn, st, rs);
       }
    }
    
    
    // 改
    public void update(){
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       try{
           conn = JdbcUtils.getConnection();
           String sql = "update users set name=?,email=? where id=?";
           st = conn.prepareStatement(sql);
           st.setString(1, "gacl");
           st.setString(2, "gacl@sina.com");
           st.setInt(3, 2);
           int num = st.executeUpdate();
           if(num>0){
               System.out.println("更新成功!!");
           }
       }catch (Exception e) {
           e.printStackTrace();
           
       }finally{
           JdbcUtils.release(conn, st, rs);
       }
    }
    
    
    // 查
    public void find(){
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       try{
           conn = JdbcUtils.getConnection();
           String sql = "select * from users where id=?";
           st = conn.prepareStatement(sql);
           st.setInt(1, 1);
           rs = st.executeQuery();
           if(rs.next()){
               System.out.println(rs.getString("name"));
           }
       }catch (Exception e) {
           
       }finally{
           JdbcUtils.release(conn, st, rs);
       }
    }
    }
    
    获取数据库自动生成的主键
         id int primary key auto_increment
     
         String sql = "insert into test1(name) values(?)";
         st = conn.prepareStatement(sql);
         st.setString(1, "aaa");
         st.executeUpdate();
         // 获取数据库自动生成的主键
         rs = st.getGeneratedKeys();
         if(rs.next()){
           System.out.println(rs.getInt(1));
         }
    
    2. 事务

    概念

    原子性(Atomicity)  �
        原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败
    
    一致性(Consistency)
        �事务必须使数据库从一个一致性状态变换到另外一个一致性状态。以转账为例子,A向B转账,假设转账之前这两个用户的钱加起来总共是2000,那么A向B转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个就是事务的一致性。
    
    隔离性(Isolation)复杂,详细介绍在下�
        事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
    
    持久性(Durability)
         持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
    
    事务的隔离级别 
        多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。
     
    事务不考虑隔离性可能会引发的问题:
       1、脏读
          脏读指一个事务读取了另外一个事务未提交的数据。
     
          这是非常危险的,假设A向B转帐100元,对应sql语句如下所示
           1.update account set money=money+100 where name='B';
           2.update account set money=money-100  where name='A';
           当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。
       2、不可重复读
           不可重复读指在一个事务内读取表中的某一行数据,多次读取结果不同。
        3、虚读(幻读)
           虚读(幻读)是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
    
    
    MySQL数据库共定义了四种隔离级别: 
       1.当把事务的隔离级别设置为read uncommitted时,会引发脏读、不可重复读和虚读
       A窗口
         set transaction isolation level  read uncommitted;--设置A用户的数据库隔离级别为Read uncommitted(读未提交)
         start transaction;--开启事务
         select * from account;--查询A账户中现有的钱,转到B窗口进行操作
         select * from account--发现a多了100元,这时候A读到了B未提交的数据(脏读)
       B窗口
         start transaction;--开启事务
         update account set money=money+100 where name='A';--不要提交,转到A窗口查询
     
     
       2.当把事务的隔离级别设置为read committed时,会引发不可重复读和虚读,但避免了脏读
       A窗口
         set transaction isolation level  read committed;
         start transaction;
         select * from account;--发现a帐户是1000元,转到b窗口
         select * from account;--发现a帐户多了100,这时候,a读到了别的事务提交的数据,两次读取a帐户读到的是不同的结果(不可重复读)
       B窗口
         start transaction;
         update account set money=money+100 where name='aaa';
         commit;--转到a窗口
     
     
       3.当把事务的隔离级别设置为repeatable read(mysql默认级别)时,会引发虚读,但避免了脏读、不可重复读
       A窗口
         set transaction isolation level repeatable read;
         start transaction;
         select * from account;--发现表有4个记录,转到b窗口
         select * from account;--可能发现表有5条记录,这时候发生了a读取到另外一个事务插入的数据(虚读)
       B窗口
         start transaction;
         insert into account(name,money) values('ggg',1000);
         commit;--转到a窗口
     
     
       4.当把事务的隔离级别设置为Serializable时,会避免所有问题
       A窗口
         set transaction isolation level Serializable;
         start transaction;
         select * from account;--转到b窗口
       B窗口
         start transaction;
         insert into account(name,money) values('ggg',1000);--发现不能插入,只能等待a结束事务才能插入
    
    
     终端查询当前事务隔离级别:select @@tx_isolation
     mysql数据库默认的事务隔离级别是:Repeatable read(可重复读)
     set transaction isolation level 隔离级别名
    

    使用

    终端使用
    
    // 开启事务
    start transaction;
    // 执行语句列表。。。
    // 提交
    commit;
     
    // 回滚(异常中)
    rollback;
    
    代码使用
        conn.setAutoCommit(false); // 通知数据库开启事务
     
    public void testTransaction1(){
         Connection conn = null;
         PreparedStatement st = null;
         ResultSet rs = null;
     
         try{
           conn = JdbcUtils.getConnection();
           conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
           String sql1 = "update account set money=money-100 where name='A'";
           st = conn.prepareStatement(sql1);
           st.executeUpdate();
           String sql2 = "update account set money=money+100 where name='B'";
           st = conn.prepareStatement(sql2);
           st.executeUpdate();
           conn.commit();//上面的两条SQL执行Update语句成功之后就通知数据库提交事务(commit)
           System.out.println("成功!!!");  //log4j
         }catch (Exception e) {
           e.printStackTrace();
         }finally{
           JdbcUtils.release(conn, st, rs);
         }
     }
    
    设置事物回滚点
     
     
     // 设置事务回滚点
     sp = conn.setSavepoint();
     
     异常中+
     conn.rollback(sp);//回滚到设置的事务回滚点
     // 回滚了要记得通知数据库提交事务
     conn.commit();
    
    3. 批处理
    JDBC实现批处理有两种方式:statement和preparedstatement
    
    Statement完成批处理
     
        st = conn.createStatement();
        // 添加要批量执行的SQL
        st.addBatch(sql1);
        st.addBatch(sql2);
        // 执行批处理SQL语句
        st.executeBatch();
        // 清除批处理命令
        st.clearBatch();
     
        优点:可以向数据库发送多条不同的SQL语句。
        缺点:SQL语句没有预编译。
       当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句
    
     PreparedStatement完成批处理
    
        String sql = "insert into testbatch(id,name) values(?,?)";
        st = conn.prepareStatement(sql);
        for(int i=1;i<1000008;i++){  //i=1000  2000
            st.setInt(1, i);
            st.setString(2, "aa" + i);
            st.addBatch();
            if(i%1000==0){
                st.executeBatch();
                st.clearBatch();
            }
        }
        st.executeBatch();
     
        优点:发送的是预编译后的SQL语句,执行效率高。
        缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。
    
    4. 大数据
    大数据LOB(Large Objects)分为:
          clob用于存储大文本
          blob用于存储二进制数据,例如图像、声音、二进制文等。
    

    MySQL

    MySQL
          blob(没有clob)存储二进制,分为:
           TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
          Text存储大文本,分为:
           TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
    
    大文本
    
    sql 
        helloContent text类型
     
    添加
     // 这种方式获取的路径,其中的空格会被使用“%20”代替
     String path = JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
     // 将“%20”替换回空格
     path = path.replaceAll("%20", " ");
     File file = new File(path);
     reader = new FileReader(file);
     st.setCharacterStream(1, reader,(int) file.length());
     int num = st.executeUpdate();
     if(num>0){
         System.out.println("插入成功!!");
     }
     //关闭流
     reader.close();
     
     
     
    读取 
     String sql = "select resume from testclob where id=2";
     st = conn.prepareStatement(sql);
     rs = st.executeQuery();
     
     String contentStr ="";
     String content = "";
     if(rs.next()){
         //使用resultSet.getString("字段名")获取大文本数据的内容
         content = rs.getString("resume");
         //使用resultSet.getCharacterStream("字段名")获取大文本数据的内容
         Reader reader = rs.getCharacterStream("resume");
         char buffer[] = new char[1024];
         int len = 0;
         FileWriter out = new FileWriter("D:\\1.txt");
         while((len=reader.read(buffer))>0){
           contentStr += new String(buffer);
           out.write(buffer, 0, len);
         }
         out.close();
         reader.close();
     }
    
    二进制
    
    sql
     helloImage longblob类型
     
      
    添加
     conn = JdbcUtils.getConnection();
     String sql = "insert into testblob(image) values(?)";
     st = conn.prepareStatement(sql);
     //这种方式获取的路径,其中的空格会被使用“%20”代替
     String path = JdbcOperaBlob.class.getClassLoader().getResource("01.jpg").getPath();
     //将“%20”替换会空格
     path = path.replaceAll("%20", " ");
     File file = new File(path);
     FileInputStream fis = new FileInputStream(file);//生成的流
     st.setBinaryStream(1, fis,(int) file.length());
     int num = st.executeUpdate();
     if(num>0){
         System.out.println("插入成功!!");
     }
     fis.close();
     
     
    读取
     String sql = "select image from testblob where id=?";
     st = conn.prepareStatement(sql);
     st.setInt(1, 1);
     rs = st.executeQuery();
     if (rs.next()) {
         //InputStream in = rs.getBlob("image").getBinaryStream();//这种方法也可以
         InputStream in = rs.getBinaryStream("image");
         int len = 0;
         byte buffer[] = new byte[1024];
     
         FileOutputStream out = new FileOutputStream("D:\\1.jpg");
         while ((len = in.read(buffer)) > 0) {
           out.write(buffer, 0, len);
         }
         in.close();
         out.close();
     }
    

    Oracle

    LOB(Large Object,大型对象)类型的字段现在用得越来越多了。
        因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据 量非常大的业务领域(如图象、档案等)。
     
    LOB类型分为种:
            BLOB二进制大型对象(Binary Large Object)
            CLOB字符型大型对象(Character Large Object)
    
    sql
        CREATE TABLE TEST_CLOB ( ID NUMBER(3), CLOBCOL CLOB)
        CREATE TABLE TEST_BLOB ( ID NUMBER(3), BLOBCOL BLOB)
    
    db.properties
        oracleDb_Driver=oracle.jdbc.driver.OracleDriver
        oracleDb_Url=jdbc:oracle:thin:@localhost:1521:GACL
        oracleDb_UserName=GACL_XDP
        oracleDb_Password=P
    
    数据库处理类
    public class JdbcUtils {
    
        private static String oracleDb_Driver = null;
        private static String oracleDb_Url = null;
        private static String oracleDb_UserName = null;
        private static String oracleDb_Password = null;
    
        static{
            try{
            //读取db.properties文件中的数据库连接信息
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties prop = new Properties();
            prop.load(in);
    
            //获取数据库连接驱动
            oracleDb_Driver = prop.getProperty("oracleDb_Driver");
            //获取数据库连接URL地址
            oracleDb_Url = prop.getProperty("oracleDb_Url");
            //获取数据库连接用户名
            oracleDb_UserName = prop.getProperty("oracleDb_UserName");
            //获取数据库连接密码
            oracleDb_Password = prop.getProperty("oracleDb_Password");
    
            //加载数据库驱动
            Class.forName(oracleDb_Driver);
    
            }catch (Exception e) {
              throw new ExceptionInInitializerError(e);
            }
      }
    
       //获取Oracle数据库连接对象
       public static Connection getOracleConnection() throws SQLException{
           return DriverManager.getConnection(oracleDb_Url, oracleDb_UserName,oracleDb_Password);
       }
    
       // 要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
       public static void release(Connection conn,Statement st,ResultSet rs){
           if(rs!=null){
               try{
                   //关闭存储查询结果的ResultSet对象
                   rs.close();
               }catch (Exception e) {
                   e.printStackTrace();
               }
               rs = null;
           }
           if(st!=null){
               try{
                   //关闭负责执行SQL命令的Statement对象
                   st.close();
               }catch (Exception e) {
                   e.printStackTrace();
               }
           }
       
           if(conn!=null){
               try{
                   //关闭Connection数据库连接对象
                   conn.close();
               }catch (Exception e) {
                   e.printStackTrace();
               }
           }
       }
    }
    
    CLOB数据 字符型
     
     public class JdbcOperaOracleClob {
     
    // 往数据库中插入一个新的CLOB对象
    public void clobInsert() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        conn = JdbcUtils.getOracleConnection();
        boolean defaultCommit = conn.getAutoCommit();
        // 开启事务,设定不自动提交
        conn.setAutoCommit(false);
        try {
            // 插入一个空的CLOB对象
            String sql = "INSERT INTO TEST_CLOB VALUES (?, EMPTY_CLOB())";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            stmt.executeUpdate();
            // 查询此CLOB对象并锁定
            sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                // 取出此CLOB对象
                oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
                // 向CLOB对象中写入数据
                BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
                //这种方式获取的路径,其中的空格会被使用“%20”代替
                String path = JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
                // 将“%20”替换回空格
                path = path.replaceAll("%20", " ");
                BufferedReader in = new BufferedReader(new FileReader(path));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            // 正式提交
            conn.commit();
            System.out.println("插入成功");
        } catch (Exception ex) {
            // 出错回滚
            conn.rollback();
            throw ex;
        }finally{
            // 恢复原提交状态
            conn.setAutoCommit(defaultCommit);
            JdbcUtils.release(conn,stmt,rs);
        }
        
    }
     
    // CLOB对象读取
    public void clobRead() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        conn = JdbcUtils.getOracleConnection();
        boolean defaultCommit = conn.getAutoCommit();
        conn.setAutoCommit(false);
        try {
            // 查询CLOB对象
            String sql = "SELECT * FROM TEST_CLOB WHERE ID=?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                // 获取CLOB对象
                oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
                // 以字符形式输出
                BufferedReader in = new BufferedReader(clob.getCharacterStream());
                BufferedWriter out = new BufferedWriter(new FileWriter("D:\\2.txt"));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                out.close();
                in.close();
            }
        } catch (Exception ex) {
            conn.rollback();
            throw ex;
        }finally{
            // 恢复原提交状态
            conn.setAutoCommit(defaultCommit);
            JdbcUtils.release(conn,stmt,rs);
        }
    }
    
    
    // 修改CLOB对象(是在原CLOB对象基础上进行覆盖式的修改)
    public void clobModify() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        conn = JdbcUtils.getOracleConnection();
        boolean defaultCommit = conn.getAutoCommit();
        // 开启事务
        conn.setAutoCommit(false);
        try {
            // 查询CLOB对象并锁定
            String sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                // 获取此CLOB对象
                oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
                // 进行覆盖式修改
                BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
                // 这种方式获取的路径,其中的空格会被使用“%20”代替
                String path = JdbcOperaClob.class.getClassLoader().getResource("data2.txt").getPath();
                // 将“%20”替换回空格
                path = path.replaceAll("%20", " ");
                BufferedReader in = new BufferedReader(new FileReader(path));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            //提交事务
            conn.commit();
        } catch (Exception ex) {
            // 出错回滚事务
            conn.rollback();
            throw ex;
        }finally{
            // 恢复原提交状态
            conn.setAutoCommit(defaultCommit);
            JdbcUtils.release(conn,stmt,rs);
        }
    }
    
    
    // 替换CLOB对象(将原CLOB对象清除,换成一个全新的CLOB对象)
    public void clobReplace() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        conn = JdbcUtils.getOracleConnection();
        boolean defaultCommit = conn.getAutoCommit();
        // 开启事务
        conn.setAutoCommit(false);
        try {
            // 清空原CLOB对象
            String sql = "UPDATE TEST_CLOB SET CLOBCOL=EMPTY_CLOB() WHERE ID=?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            stmt.executeUpdate();
            
            // 查询CLOB对象并锁定
            sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                // 获取此CLOB对象
                oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
                // 更新数据
                BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
                // 这种方式获取的路径,其中的空格会被使用“%20”代替
                String path = JdbcOperaClob.class.getClassLoader().getResource("db.properties").getPath();
                // 将“%20”替换回空格
                path = path.replaceAll("%20", " ");
                BufferedReader in = new BufferedReader(new FileReader(path));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            // 正式提交
            conn.commit();
        } catch (Exception ex) {
            // 出错回滚
            conn.rollback();
            throw ex;
        } finally {
            // 恢复原提交状态
            conn.setAutoCommit(defaultCommit);
            JdbcUtils.release(conn, stmt, rs);
        }
    }
    }
    
     处理BLOB二进制数据
     
        Oracle定义了一个BLOB字段用于保存二进制数据,但这个字段并不能存放真正的二进制数据,只能向这个字段存一个指针,然后把数据放到指针所指向的Oracle的LOB段中, LOB段是在数据库内部表的一部分。因而在操作Oracle的Blob之前,必须获得指针(定位器)才能进行Blob数据的读取和写入。
       如何获得表中的Blob指针呢? 可以先使用insert语句向表中插入一个空的blob(调用oracle的函数empty_blob()),这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样就可得到BLOB对象,从而读写blob数据了。
     
       1、插入空blob:insert into testblob(id,image) values(?,empty_blob())
       2、获得blob的cursor:
         select image from testblob where id=? for update �注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突。
         Blob b = rs.getBlob("image");
       3、利用 io和获取到的cursor往数据库读写数据
       注意:以上操作需开启事务。
     
     
     
     public class JdbcOperaOracleBlob {
     
    // 向数据库中插入一个新的BLOB对象
    public void blobInsert() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        boolean defaultCommit = true;
        try {
            conn = JdbcUtils.getOracleConnection();
            //得到数据库事务处理的默认提交方式
            defaultCommit = conn.getAutoCommit();
            //1、开启事务
            conn.setAutoCommit(false);
            //2、插入一个空的BLOB对象
            String sql = "INSERT INTO TEST_BLOB VALUES (?, EMPTY_BLOB())";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            stmt.executeUpdate();
            //3、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
            sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                //4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
                oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
                //5、使用IO向BLOB对象中写入数据
                BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
                BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            //6、提交事务
            conn.commit();
        } catch (Exception ex) {
            //7、出错回滚事务
            conn.rollback();
            throw ex;
        } finally {
            //8、恢复数据库事务处理的默认提交方式
            conn.setAutoCommit(defaultCommit);
            //释放资源
            JdbcUtils.release(conn, stmt, rs);
        }
        
    }
    
    
    // 修改BLOB对象(是在原BLOB对象基础上进行覆盖式的修改)
    public void blobModify() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        boolean defaultCommit = true;
        try {
            conn = JdbcUtils.getOracleConnection();
            //得到数据库事务处理的默认提交方式
            defaultCommit = conn.getAutoCommit();
            //1、开启事务
            conn.setAutoCommit(false);
            //2、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
            String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                //3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
                oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
                //4、使用IO向BLOB对象中写入数据
                BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
                BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("02.jpg"));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            //5、提交事务
            conn.commit();
        } catch (Exception ex) {
            //6、出错回滚事务
            conn.rollback();
            throw ex;
        } finally {
            //8、恢复数据库事务处理的默认提交方式
            conn.setAutoCommit(defaultCommit);
            //释放资源
            JdbcUtils.release(conn, stmt, rs);
        }
    }
    
    // 替换BLOB对象(将原BLOB对象清除,换成一个全新的BLOB对象)
    public void blobReplace() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        boolean defaultCommit = true;
        try {
            conn = JdbcUtils.getOracleConnection();
            //得到数据库事务处理的默认提交方式
            defaultCommit = conn.getAutoCommit();
            //1、开启事务
            conn.setAutoCommit(false);
            //2、清空原BLOB对象
            String sql = "UPDATE TEST_BLOB SET BLOBCOL=EMPTY_BLOB() WHERE ID=?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            stmt.executeUpdate();
            //3、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
            sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                //4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
                oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
                //5、使用IO向BLOB对象中写入数据
                BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
                BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            //6、提交事务
            conn.commit();
        } catch (Exception ex) {
            //7、出错回滚事务
            conn.rollback();
            throw ex;
        } finally {
            //8、恢复数据库事务处理的默认提交方式
            conn.setAutoCommit(defaultCommit);
            //释放资源
            JdbcUtils.release(conn, stmt, rs);
        }
    }
    
    // BLOB对象读取
    public void blobRead() throws Exception {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        boolean defaultCommit = true;
        try {
            conn = JdbcUtils.getOracleConnection();
            //得到数据库事务处理的默认提交方式
            defaultCommit = conn.getAutoCommit();
            //1、开启事务
            conn.setAutoCommit(false);
            //2、查询BLOB对象
            String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 1);
            rs = stmt.executeQuery();
            if (rs.next()) {
                //3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
                oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
                //4、以二进制流的形式输出
                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("D:/1.jpg"));
                BufferedInputStream in = new BufferedInputStream(blob.getBinaryStream());
                int c;
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
                in.close();
                out.close();
            }
            //5、提交事务
            conn.commit();
        } catch (Exception ex) {
            //6、出错回滚事务
            conn.rollback();
            throw ex;
        } finally {
            //8、恢复数据库事务处理的默认提交方式
            conn.setAutoCommit(defaultCommit);
            //释放资源
            JdbcUtils.release(conn, stmt, rs);
        }
        
    }}
    
     通过JDBC操纵Oracle数据库的LOB字段,不外乎插入、修改、替换、读取四种方式,掌握起来并不难。观察上述程序对LOB类型字段的存取,我们可以看出,较之其它类型字段,有下面几个显著不同的特点:
     
       1、必须取消自动提交。
     
       存取操作开始前,必须用setAutoCommit(false)取消自动提交。其它类型字段则无此特殊要求。这是因为存取LOB类型字段时,通常要进行多次操作可以完成。不这样的话,Oracle将抛出“读取违反顺序”的错误。
     
       2、插入方式不同。
     
       LOB数据不能象其它类型数据一样直接插入(INSERT)。插入前必须先插入一个空的LOB对象,CLOB类型 的空对象为EMPTY_CLOB(),BLOB类型的空对象为EMPTY_BLOB()。之后通过SELECT命令查询得到先前插入的记录并锁定,继而将 空对象修改为所要插入的LOB对象。
     
       3、修改方式不同。
     
       其它类型的字段修改时,用UPDATE … SET…命令即可。而LOB类型字段,则只能用SELECT … FOR UPDATE命令将记录查询出来并锁定,然后才能修改。且修改也有两种改法:一是在原数据基础上的修改(即覆盖式修改),执行SELECT … FOR UPDATE后再改数据;二是替换(先将原数据清掉,再修改),先执行UPDATE命令将LOB字段之值设为空的LOB对象,然后进行第一种改法。建议使 用替换的方法,以实现与其它字段UPDATE操作后一样的效果。
     
       4、存取时应使用由数据库JDBC驱动程序提供的LOB操作类。
     
       对于Oracle数据库,应使用oracle.sql.CLOB和oracle.sql.BLOB。不使用由数据库JDBC驱动程序提供的LOB类时,程序运行时易于出现“抽象方法调用”的错误,这是因为JDBC所定义的java.sql.Clob与 java.sql.Blob接口,其中的一些方法并未在数据库厂家提供的驱动程序中真正实现。
     
       5、存取手段与文件操作相仿。
     
       对于BLOB类型,应用InputStream/OutputStream类,此类不进行编码转换,逐个字节存取。oracle.sql.BLOB类相应提供了getBinaryStream()和getBinaryOutputStream()两个方法,前一个 方法用于读取Oracle的BLOB字段,后一个方法用于将数据写入Oracle的BLOB字段。
     
       对于CLOB类型,应用Reader/Writer类,此类进行编码转换。oracle.sql.CLOB类相应 提供了getCharacterStream()和getCharacterOutputStream()两个方法,前一个方法用于读取Oracle的 CLOB字段,后一个方法用于将数据写入Oracle的CLOB字段。
     
       需要说明的是,为了大幅提高程序执行效率,对BLOB/CLOB字段的读写操作,应该使用缓冲操作类(带 Buffered前缀),即:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。 例程中全部使用了缓冲操作类。
    

    相关文章

      网友评论

        本文标题:JavaWeb基础恢复之操作数据库

        本文链接:https://www.haomeiwen.com/subject/qgzmlftx.html