使用JDBC处理大数据(Large Objects)

来源:互联网 发布:龙腾网络传奇 编辑:程序博客网 时间:2024/06/06 04:57
 

使用JDBC处理大数据(Large Objects)

在实际开发中,程序需要把大文本或二进制数据保存到数据库(例如一个电影、一个很长很长的大文本要存入数据库)中,用JDBC该怎么操作呢?

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

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

(1)       clob用于存储大文本。Text

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

(3)       对MySql而言之有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:

1)  TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

2)  TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

2、处理大文本数据

案例1,向数据库的表中插入或读取大文本数据。

准备:

(1)com.hbsi.utils包下的DBManager类负责获得连接以及资源的释放。

(2)属性文件db.properties保存了建立连接时需要的参数。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/demodb
username=root
password=root

(3)MySQL的驱动

(4)src目录下放置一个文本文件1.txt

(5)创建数据库、表
create database demodb;
use demodb;
create table testclob
(
   id int primary key auto_increment,
   resume text
);

 

编写代码:Demo1.java

public void insert(){

       Connection conn = null;

       PreparedStatement st = null;

       ResultSet rs = null;

       try{

              conn = DBManager.getConnection();

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

              st = conn.prepareStatement(sql);

              //st.setCharacterStream()方法的第二个参数需要一个流对象,第三个但是需要大文本文件的长度,因此通过Demo1.class调用getcLassLoader()方法得到类加载器后没有直接得到输入流对象,而是先得到相关文件的路径和文件名,再构建一个File对象,利用该File对象得到相关文件的长度

              //该方法自动从流中读取数据存入表格中

              String path = Demo1.class.getClassLoader().getResource("1.txt").getPath();

              File f = new File(path);

              st.setCharacterStream(1, new FileReader(path),(int)f.length() );

              //setCharacterStream()方法在jdk1.6之前的版本第三个参数只能是int类型,jdk1.6之后可以是long类型(重载方法)

              int num = st.executeUpdate();

              if(num>0){

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

              }

       }catch (Exception e) {

              throw new RuntimeException(e);

       }finally{

              DBManager.release(conn, st, rs);

       }

}

public void find(){

       Connection conn = null;

       PreparedStatement st = null;

       ResultSet rs = null;

       try{

              conn = DBManager.getConnection();

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

              st = conn.prepareStatement(sql);

              rs = st.executeQuery();

              if(rs.next()){

                     Reader reader = rs.getCharacterStream("resume");

                     char buffer[] = new char[1024];//缓冲区不能太大,大文本一点一点地流进来

                     int len = 0;

                           

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

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

                            writer.write(buffer,0,len);

                     }

                     reader.close();

                     writer.close();

              }

       }catch (Exception e) {

              throw new RuntimeException(e);

       }finally{

              DBManager.release(conn, st, rs);

       }

}

代码段如果写成这样:

if(rs.next()){

       String result=rs.getString(“resume”);

       System.out.println(result);

}

也能执行,可在控制台窗口看到大文本的输出。可是在实际的操作中千万不要这样写!因为这样做是将数据库中的大文本读到内存的字符串中,如果该大文本是非常大的,500M或1G,系统就立刻在内存中开辟500M或1G的内存,系统立即就崩溃了,死机。这时一定要用流,一点一点地将数据库的大文本内容流进来。

 

3、大二进制数据

案例2,向数据库的表中插入或获取大二进制数据。

准备:

(1)com.hbsi.utils包下的DBManager类负责获得连接以及资源的释放。

(2)属性文件db.properties保存了建立连接时需要的参数。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/demodb
username=root
password=root

(3)MySQL的驱动

(4)src目录下一个图片文件1.jpg

(5)创建表
create table testblob
(
   id int primary key auto_increment,
   images blob
);

编写代码:Demo2.java

public void insert(){

       Connection conn = null;

       PreparedStatement st = null;

       ResultSet rs = null;

       try{

              conn = DBManager.getConnection();

              String sql = "insert into testblob(images) values(?)";

              st = conn.prepareStatement(sql);

              String path = Demo1.class.getClassLoader().getResource("1.jpg").getPath();

              File f = new File(path);

              st.setBinaryStream(1, new FileInputStream(path), (int) f.length());

                    

              int num = st.executeUpdate();

              if(num>0){

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

              }

       }catch (Exception e) {

              throw new RuntimeException(e);

       }finally{

              DBManager.release(conn, st, rs);

       }

}

代码运行后,在mysql中输入select * from testblob;语句查看图片,看不了,这时即使能看也是乱码,而且停不了,很难退出来。可以用mysql的工具软件来查看。或是通过如下的代码查看:

public void find(){

       Connection conn = null;

       PreparedStatement st = null;

       ResultSet rs = null;

       try{

              conn = DBManager.getConnection();

              String sql = "select images from testblob where id=1";

              st = conn.prepareStatement(sql);

              rs = st.executeQuery();

              if(rs.next()){

                     InputStream in = rs.getBinaryStream("images");

                     byte buffer[] = new byte[1024];

                     int len = 0;

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

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

                            out.write(buffer, 0, len);

                     }

                     in.close();

                     out.close();

              }

       }catch (Exception e) {

              throw new RuntimeException(e);

       }finally{

              DBManager.release(conn, st, rs);

       }

}

2、  使用JDBC处理二进制数据:

对于MySql中的BLOB类型,可调用如下方法设置:

PreparedStatement.setBinaryStream(i,inputStream,length);

对于MySql中的BLOB类型,可调用如下方法获取:

InputStream in=resultSet.getBinaryStream(i);

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

 

注意:今天讲的大数据的处理在实际的项目开发中不能用。想一想如果真的向数据库中存入大数据,比如1G的电影,需要通过连接向数据库发送1G的数据,或是从数据库中读取1G的数据,这就导致该用户占用连接的时间超长,连接是数据库非常宝贵的资源,你占用了连接,别人就占用不了。因此在实际的开发中,为了提高数据库的访问性能,我们通常不会将大数据存入到数据库中,而是把它们存到硬盘中,数据库中只存储大数据文件的路径。