当前位置:Gxlcms > 数据库问题 > JDBC 学习笔记—— 大数据…

JDBC 学习笔记—— 大数据…

时间:2021-07-01 10:21:17 帮助过:2人阅读

转自:http://even2012.iteye.com/blog/1886950

 

 

1、使用JDBC处理大数据

 

    在实际开发中,程序需要把大文本或二进制数据保存到数据库。

 

     

 

    基本概念:大数据也称之为LOB(Large Objects),LOB又分为:clob和blob

 

        (a)clob用于存储大文本。(mysql 中采用Text)

 

        (b)blob用于存储二进制数据,例如图像、声音、二进制文等。

 

     

 

    对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text,其体系中的Text和blob分别又分为:

 

           (a)Text ——TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

 

           (b)blob ——TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

 

 

 


 

 

 

2、使用JDBC处理大文本

 

    (1) 保存数据—— 对于MySQL中的Text类型,可调用如下方法设置:

 

            PreparedStatement.setCharacterStream(i, reader, length);

 

            //注意length长度须设置,并且设置为int型

 

     

 

    (2) 获取数据—— 对于MySQL中的Text类型,可调用如下方法获取:

 

            (a) reader = resultSet. getCharacterStream(i);

 

            (b) reader = resultSet.getClob(i).getCharacterStream();

 

            (c) string s = resultSet.getString(i);

 

        

 

Demo样例:

 

public class Demo1 

 

   

 

  @Test

 

  public void insert() throws SQLException, FileNotFoundException{ 

 

        Connection conn null;

 

        PreparedStatement st null;

 

        ResultSet rs null;

 

     

 

        try{

 

                  conn JdbcUtils.getConnection();

 

                  String sql "insert into testclob(id,resume) values(?,?)";

 

                  st conn.prepareStatement(sql);

 

                  st.setString(1, "1");

 

             

 

                  File file new File("src/1.txt");

 

                  FileReader reader new FileReader(file);

 

                  st.setCharacterStream(2, reader, (int) file.length());

 

                  int num st.executeUpdate();

 

                  if(num>0){

 

                            System.out.println("插入成功!!");

 

                  }

 

        }finally{

 

                  JdbcUtils.release(conn, st, rs);

 

        }

 

  }

 

 

 

  @Test

 

  public void read() throws SQLException, IOException{

 

        Connection conn null;

 

        PreparedStatement st null;

 

        ResultSet rs null; 

 

        try{

 

              conn JdbcUtils.getConnection();

 

              String sql "select id,resume from testclob where id=‘1‘";

 

              st conn.prepareStatement(sql);

 

              rs st.executeQuery();

 

              if(rs.next()){

 

                    //String resume rs.getString("resume");

 

                    Reader reader rs.getCharacterStream("resume");

 

                    FileWriter writer new FileWriter("c:\\1.txt");

 

                    try {

 

                          int len 0;

 

                          char buffer[] new char[1024];

 

                          while ((len reader.read(buffer)) 0) {

 

                            writer.write(buffer, 0, len);

 

                          }

 

                    finally {

 

                          if (reader != null) {

 

                                reader.close();

 

                          }

 

                          writer.close();

 

                    }

 

              }

 

        }finally{

 

              JdbcUtils.release(conn, st, rs);

 

        }

 

  }

 

}

 

 

 

 

 


 

 

 

3、使用JDBC处理二进制数据

 

    (1) 保存数据—— 对于MySQL中的BLOB类型,可调用如下方法设置:

 

            PreparedStatement. setBinaryStream(i , inputStream, length);

 

     

 

    (2) 获取数据—— 对MySQL中的BLOB类型,可调用如下方法获取:

 

           (a)  InputStream in  = resultSet.getBinaryStream(i);

 

           (b) InputStream in  = resultSet.getBlob(i).getBinaryStream();

 

         

 

Demo样例:

 

public class Demo2 {

 

    

 

  @Test

 

  public void insert() throws SQLException, FileNotFoundException{

 

    Connection conn null;

 

    PreparedStatement st null;

 

    ResultSet rs null;

 

    try{

 

      conn JdbcUtils.getConnection();

 

      String sql "insert into testblob(id,image) values(?,?)";

 

      st conn.prepareStatement(sql);

 

      st.setString(1, "1");

 

      File file new File("src/1.jpg");

 

      FileInputStream in new FileInputStream(file);

 

      st.setBinaryStream(2, in, (int) file.length());

 

      st.executeUpdate();

 

    }finally{

 

      JdbcUtils.release(conn, st, rs);

 

    }

 

  }

 

 

 

  @Test

 

  public void read() throws SQLException, IOException{

 

    Connection conn null;

 

    PreparedStatement st null;

 

    ResultSet rs null;

 

    try{

 

      conn JdbcUtils.getConnection();

 

      String sql "select id,image from testblob where id=‘1‘";

 

      rs conn.prepareStatement(sql).executeQuery();

 

      if(rs.next()){

 

        InputStream in rs.getBinaryStream("image");

 

        OutputStream out new FileOutputStream("c:\\1.jpg");;

 

        try {

 

          int len 0;

 

          byte buffer[] new byte[1024];

 

          while ((len in.read(buffer)) 0) {

 

            out.write(buffer, 0, len);

 

          }

 

        finally {

 

          if (in != null)

 

            in.close();

 

          if (out != null)

 

            out.close();

 

        }

 

      }

 

    }finally{

 

      JdbcUtils.release(conn, st, rs);

 

    }

 

  }

 

}

 

 

 


 

 

 

4、Oracle中大数据处理

 

        Oracle定义了一个BLOB字段用于保存二进制数据,但这个字段并不能存放真正的二进制数据,只能向这个字段存一个指针,然后把数据放到指针所指向的Oracle的LOB段中, LOB段是在数据库内部表的一部分。

 

        因而在操作Oracle的Blob之前,必须获得指针(定位器)才能进行Blob数据的读取和写入。

 

        如何获得表中的Blob指针呢? 可以先使用insert语句向表中插入一个空的blob(调用oracle的函数empty_blob()  ),这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样就可得到BLOB对象,从而读写blob数据了。

 

 

 

    Oracle中LOB类型的处理步骤

 

    (1)  插入空blob ——  insert into test(id,image) values(?,empty_blob());

 

    (2)  获得blob的cursor ——  select image from test where id= ? for update;  

 

                                                      Blob b = rs.getBlob(“image”);

 

        注意:  须加for update,锁定该行,直至该行被修改完毕,保证不产生并发冲突。

 

    (3)  利用 io,和获取到的cursor往数据库读写数据

 

        注意:以上操作需开启事务。

 

    备注:本文关于Oracle中LOB类型数据处理的操作仅供参考,详细内容参见 有关Oracle的博文。

 

 

 


 

 

 

5、使用JDBC进行批处理

 

    业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。

 

    实现批处理有两种方式,

 

            第一种方式: Statement.addBatch(sql) (其实是将sql语句 放在了一个 list 集合中。)

 

            第二种方式:  PreparedStatement.addBatch() (其实是将sql语句 放在了一个 list 集合中。)

 

    执行批处理SQL语句

 

            executeBatch()方法:执行批处理命令

 

            clearBatch()方法:清除批处理命令(实际上是清除 List集合中的SQL语句,否则会造成内存溢出。)

 

 

 

    Demo样例:第一种方式:Statement.addBatch(sql)

 

 @Test
 public void test1() throws SQLException{

 

            Connection conn = null;

 

            Statement st = null;

 

            ResultSet rs = null;

 

            try {

 

                    conn = JdbcUtil.getConnection();

 

                    String sql1 = "insert into user(name,password,email,birthday)  values(‘kkk‘,‘123‘,‘abc@sina.com‘,‘1978-08-08‘)";

 

                    String sql2 = "update user set password=‘123456‘ where id=3";

 

                    st = conn.createStatement();

 

                    st.addBatch(sql1);  //把SQL语句加入到批命令中

 

                    st.addBatch(sql2);  //把SQL语句加入到批命令中

 

                    st.executeBatch();

 

                    st.clearBatch();

 

            } finally{

 

                 JdbcUtil.free(conn, st, rs);

 

            }

 

 }

 

 

 


 

 

 

6、采用Statement.addBatch(sql)方式实现批处理的优缺点

 

        优点:可以向数据库发送多条不同的SQL语句。

 

        缺点:SQL语句没有预编译。当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。

 

            例如:

 

               Insert into user(name,password) values(‘aa’,’111’);

 

               Insert into user(name,password) values(‘bb’,’222’);

 

               Insert into user(name,password) values(‘cc’,’333’);

 

               Insert into user(name,password) values(‘dd’,’444’);

 

         

 


 

 

 

7、实现批处理的第二种方式:PreparedStatement.addBatch() 

 

    Demo样例:第二种 方式

 

 @Test
 public void test2() throws SQLException{

 

        conn = JdbcUtil.getConnection();

 

        String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";

 

        st = conn.prepareStatement(sql);

 

        for(int i=0;i<50000;i++){

 

                st.setString(1, "aaa" + i);

 

                st.setString(2, "123" + i);

 

                st.setString(3, "aaa" + i + "@sina.com");

 

                st.setDate(4,new Date(1980, 10, 10));

 

                 

 

                st.addBatch();

 

                if(i00==0){      //为防止(list集合) 内存溢出:设定每累加1000条数据就向数据库发送一次

 

                        st.executeBatch();

 

                        st.clearBatch();

 

                }

 

        }

 

        st.executeBatch(); //当剩余的条数小于1000条时就不会被发送到数据库,所以此处要在发送一次。

 

 

 

 


 

 

 

8、采用PreparedStatement.addBatch()实现批处理的优缺点

 

    优点:发送的是预编译后的SQL语句,执行效率高。

 

    缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。

 

 

 


 

 

 

9、获得MySQL数据库自动生成的主键

 

    示例:

 

        Connection conn = JdbcUtil.getConnection(); 

 

        String sql = "insert into user(name,password,email,birthday)  values(‘abc‘,‘123‘,‘abc@sina.com‘,‘1978-08-08‘)";

 

                                                              //重载函数:返回生成的自动主键

 

        PreparedStatement st = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS );         

 

        st.executeUpdate();

 

 

 

        ResultSet rs = st.getGeneratedKeys();  //得到插入行的主键

 

        if(rs.next())

 

             System.out.println(rs.getObject(1));

 

    注:此参数仅对insert操作有效。

 

 

 

 Demo样例: 

 

public class Demo4 

 

  

 

  public static void main(String[] args) throws SQLException 

 

        Connection conn null;

 

        PreparedStatement st null;

 

        ResultSet rs null; 

 

        try{

 

              conn JdbcUtils.getConnection();

 

              String sql "insert into test(name) values(‘aaa‘)";

 

              st conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);

 

              st.executeUpdate();

 

         

 

              rs st.getGeneratedKeys();

 

              if(rs.next()){

 

                    System.out.println(rs.getInt(1));

 

              

 

        }finally{

 

              JdbcUtils.release(conn, st, rs);

 

        }

 

  

 

}

 

 

 

 


 

 

 

 

 

10、JDBC调用存储过程

 

编写存储过程(参看mysql文档)

 

本文重在JDBC对存储过程的调用,关于其知识内容,将在《Oracle数据库 知识》博文中详细介绍

 

 存储过程Demo样例:

 

 CREATE PROCEDURE demoSp (IN inputParam VARCHAR(255) ,INOUT  inOutParam varchar(255) )

 

     BEGIN

 

             SELECT CONCAT ( ‘ZYXW---- ‘, inputParam ) into  inOutParam ;

 

     END

 

 

 

在Java中,JDBC对存储过程的调用 (这才是本文重点):

 

    (1) 得到CallableStatement,并调用存储过程:

 

            CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");     

 

    (2) 设置参数,注册返回值,得到输出

 

            cStmt.setString(1, "abcdefg");

 

            cStmt.registerOutParameter(2, Types.VARCHAR);    //类型参数值参见JDK中:java.sql.Types

 

            cStmt.execute();

 

            System.out.println(cStmt.getString(2));

 

小常识:“存储过程”在金融证券 行业中应用的非常广泛,并且将会保密其表结构和字段,完全使用公开的存储过程来实现表数据的调用。

 

Demo样例:

 

    public class Demo5 

 

              

 

              public static void main(String[] args) throws SQLException {

 

             

 

                    Connection conn null;

 

                    CallableStatement  st null;

 

                    ResultSet rs null;

 

                 

 

                    try{

 

                          conn JdbcUtils.getConnection();

 

                          st conn.prepareCall("{call demoSp(?,?)}");

 

                          st.setString(1, "aaaaa");

 

                          st.registerOutParameter(2, Types.VARCHAR);

 

                          st.execute();

 

                     

 

                          System.out.println(st.getString(2)); 

 

                    }finally{

 

                          JdbcUtils.release(conn, st, rs);

 

                    }

 

              

 

    }

 

 

 

 


 

  

 

11、事务的概念

 

        事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部都成功,要么全部不成功。

 

        例如:A——B转帐,对应于如下两条sql语句

 

                 update from account set money=money+100 where name=‘b’;

 

                 update from account set money=money-100 where name=‘a’;

 

        数据库默认事务是自动提交的,也就是发一条sql它就执行一条。如果想多条sql放在一个事务中执行,则需要使用如下语句。

 

        数据库开启事务命令

 

        start transaction  开启事务

 

        Rollback  回滚事务

 

        Commit   提交事务

 

         

 

        Demo:

 

            Start transaction
                
                
            commit

 

 

 

Demo样例:

 

public static void main(String[] args) throws SQLException 

 

        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=‘aaa‘";

 

              String sql2 "update account set money=money+100 where name=‘bbb‘";

 

         

 

              st conn.prepareStatement(sql1);

 

              st.executeUpdate();

 

         

 

              int 1/0;    // 人为制造异常,验证事务

 

         

 

              st conn.prepareStatement(sql2);

 

              st.executeUpdate();

 

         

 

              conn.commit();    // Commit   提交事务

 

        }finally{

 

              JdbcUtils.release(conn, st, rs);

 

        

 

  }

 

 

 


 

 

 

12、JDBC控制事务语句

 

    当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交在它上面发送的SQL语句。若想关闭这种默认提交方式,让多条SQL在一个事务中执行,可使用下列语句:

 

    (1) JDBC控制事务语句

 

        Connection.setAutoCommit(false);     //相当于 start transaction

 

        Connection.rollback();     //相当于  rollback

 

        Connection.commit();     //相当于   commit

 

 

 

    (2) 设置事务回滚点

 

        Savepoint sp = conn.setSavepoint();

 

        Conn.rollback(sp);    // 会滚到指定的位置,该位置之前的操作任然有效执行,因为需要被提交

 

        Conn.commit();   //回滚后必须要提交

 

 

 

Demo样例:事务回滚点——演示银行转帐案例

 

  public static void main(String[] args) throws SQLException 

 

        Connection conn null;

 

        PreparedStatement st null;

 

        ResultSet rs null;

 

        Savepoint sp null;

 

        try{

 

              conn JdbcUtils.getConnection();   //mysql repeatable read

 

人气教程排行