JDBC操作大数据文件

在实际的开发过程中,我们可能需要把大文本或者二进制数据存储到数据库中,下面我们一起来学习一个如何使用JDBC向mysql中插入大文本数据。
在数据库中,大数据称为LOB(Large Objects),而LOB可以分为,clob和blob:

  • clob用于存储大文本Text
  • blob用于存储二进制数据,例如图像、声音、二进制文等

    在mysql中,提供了以下的数据类型来存储clob和blob:

  • TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)、LONGTEXT(4G)
  • TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

下面我们开始jdbc操作大数据文本text的例子。

1 . 新建一个数据库表:

test/bigtext

create table bigtext(
    id int primary key auto_increment,
    name varchar(20),
    content MEDIUMTEXT
);

2. 新建一个项目
导入mysql连接驱动包,这里我们要导入最新mysql-connector-java-5.1.40-bin.jar版本,然后准备好数据库配置文件和数据库连接工具类
详见我写的另一篇文章: 自己写一个数据库连接工具类

3. 实现插入大文本代码

public static boolean insertBigtext(String name,String path){
        Connection conn = null;
        PreparedStatement pre = null;
        try{
            //获取连接
            conn = mysqlConnUtil.getConn();
            //获取传输器
            pre = conn.prepareStatement("insert into bigtext values(null,?,?)");
            pre.setString(1, name);
            File file = new File(path);
            pre.setCharacterStream(2, new FileReader(file), file.length());
            return pre.executeUpdate() > 1 ? true : false;
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            mysqlConnUtil.release(conn, pre, null);
            return false;
        }
    }

这里要注意一个版本的问题,file.length()返回的数据是一个long类型的数据。
而我们查看JDK关于 PreparedStatement接口的方法描述时,可以发现

 //将给定参数设置为给定 Reader 对象,该对象具有给定字符数长度。
 //JDK1.2以上支持
 void setCharacterStream(int parameterIndex, Reader reader, int length) 

 // 将指定参数设置为给定 Reader 对象,该对象具有给定字符数长度。 
 //JDK1.6以上支持
 void setCharacterStream(int parameterIndex, Reader reader, long length) 

当我们使用较低版本的mysql-connector时,如果不支持jdk1.6,那么就需要对file.length()进行类型转换为int类型,否则会报错。

4. 准备一个10M大文件,1.txt

5. 在main函数中调用方法

    public static void main(String[] args) throws Exception {
        insertBigtext("java jdbc","1.txt"); 
    }

当我们运行的时候,发现报错了

com.mysql.jdbc.PacketTooBigException: Packet for query is too large (10886452 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
    at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3675)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2506)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
    at com.chen.Main.Main.insertBigtext(Main.java:34)
    at com.chen.Main.Main.main(Main.java:78)
Packet for query is too large (10886452 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.

上面这段错误信息表明,我们程序的Packet 太大了,超出了数据库设置的max_allowed_packet,需要修改一个这个参数。
为什么会出现这个错误呢,当我们的程序向数据库提交sql的时候,是通过一个数据包发送过去的,数据库为了保证安全和稳点,需要设置一个max_allowed_packet来保证用户不能一次性插入过大的数据。
我们在数据库的安装目录找到my.ini,修改max_allowed_packet这个属性的值为64m,重新启动数据库。运行项目:
这个时候又出现了一个新的问题:

The size of BLOB/TEXT data inserted in one transaction is greater than 10% of redo log size. Increase the redo log size using innodb_log_file_size.

这是由于mysql默认的数据库innodb数据库引擎。
我们可以使用命令查看数据库使用的引擎

数据库引擎

默认情况下,MySQL 采用 autocommit 模式运行。这意味着,当执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中,同时记录锁也会被释放。那么事务提交后,在底层做了什么呢?
1. 把事务写入日志缓冲(log buffer),日志缓冲把事务刷新到事务日志.
2. 把事务写入缓冲池(Buffer pool).
数据库默认的innodb_log_file_size过小,导致我们在插入大文本的时候,数据库把事务写入日记缓冲的时候发生了错误。我们修改my.ini 中的innodb_log_file_size = 64M
(innodb_log_buffer_size 日志缓冲区大小 ,默认8M,一般不需要设置太大,除非有BLOB字段)
再重启一下数据库,并运行项目,插入数据库成功。

另外,还有一个问题需要注意一下
以前在进行大文本的插入时,还会发生java内存溢出的问题。这个时候需要配置两个参数,来设置java虚拟机的运行分配内存:

-Xms64M
-Xmx64M
-Xmsn
Specify the initial size, in bytes, of the memory allocation pool. This value must be a multiple of 1024 greater than 1MB. Append the letter k or K to indicate kilobytes, or m or M to indicate megabytes. The default value is chosen at runtime based on system configuration. For more information, see HotSpot Ergonomics 
Examples:
       -Xms6291456
       -Xms6144k
       -Xms6m


-Xmxn
Specify the maximum size, in bytes, of the memory allocation pool. This value must a multiple of 1024 greater than 2MB. Append the letter k or K to indicate kilobytes, or m or M to indicate megabytes. The default value is chosen at runtime based on system configuration. For more information, see HotSpot Ergonomics 
Examples:
       -Xmx83886080
       -Xmx81920k
       -Xmx80m

-Xmsn用来设置虚拟机的初始分配内存,也就是最小内存,-Xmxn用来分配虚拟机分配的最大内存

那么在eclipse中要如何配置这两个参数呢:
我们需要打开Run Configurations中进行arguments设置:
设置java运行参数

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值