JDBC读写MySQL的大字段数据

本文涉及的产品
RDS AI 助手,专业版
RDS Agent(兼容OpenClaw),2核4GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介:
不管你是新手还是老手,大字段数据的操作常常令你感到很头痛。因为大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的。而非一般的字段,一次即可读出数据。本人以前用到Spring+iBatis架构来操作大字段,结果以惨烈失败而告终,在网上寻求解决方案,也没找到答案。最终以JDBC来实现了大字段操作部分。
 
本文以MySQL为例,通过最基本的JDBC技术来处理大字段的插入、读取操作。
 
环境:
MySQL5.1
JDK1.5
 
一、认识MySQL的大字段类型
 
BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
 
有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。
 
BLOB 列被视为二进制字符串(字节字符串)。TEXT列被视为非二进制字符串(字符字符串)。BLOB列没有字符集,并且排序和比较基于列值字节的数值值。TEXT列有一个字符集,并且根据字符集的 校对规则对值进行排序和比较。
 
在TEXT或BLOB列的存储或检索过程中,不存在大小写转换。
 
当未运行在严格模式时,如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值,值被截取以保证适合。
 
几种类型的大字段最大长度说明:
TINYBLOB最大长度为255(2^[8]–1)字节的BLOB列。
TINYTEXT最大长度为255(2^[8]–1)字符的TEXT列。
BLOB[(M)]最大长度为65,535(2^[16]–1)字节的BLOB列。可以给出该类型的可选长度M。如果给出,则MySQL将列创建为最小的但足以容纳M字节长的值的BLOB类型。
TEXT[(M)]最大长度为65,535(2^[16]–1)字符的TEXT列。可以给出可选长度M。则MySQL将列创建为最小的但足以容纳M字符长的值的TEXT类型。
MEDIUMBLOB最大长度为16,777,215(2^[24]–1)字节的BLOB列。
MEDIUMTEXT最大长度为16,777,215(2^[24]–1)字符的TEXT列。
LONGBLOB最大长度为4,294,967,295或4GB(2^[32]–1)字节的BLOB列。LONGBLOB列的最大有效(允许的)长度取决于客户端/服务器协议中配置最大包大小和可用的内存。
LONGTEXT最大长度为4,294,967,295或4GB(2^[32]–1)字符的TEXT列。LONGTEXT列的最大有效(允许的)长度取决于客户端/服务器协议中配置最大包大小和可用的内存。
 
二、创建测试环境
 
create  table  user ( 
    id  int(11)  not  null auto_increment, 
     name  varchar(50)  not  null
    pswd  varchar(50)  default  null
    pic longblob, 
    remark longtext, 
     primary  key (id) 
);
 
三、插入读取blob
 
import lavasoft.common.DBToolkit; 

import java.io.*; 
import java.sql.*; 

/** 
* 操作MySQL5的blob字段 

* @author leizhimin 2009-12-3 11:34:50 
*/
 
public  class BlobTest { 
         public  static  void main(String[] args) { 
                insertBlob(); 
                queryBlob(); 
        } 

         public  static  void insertBlob() { 
                Connection conn = DBToolkit.getConnection(); 
                PreparedStatement ps =  null
                 try { 
                        String sql =  "insert into testdb.user (name, pswd, pic) values (?, ?, ?)"
                        ps = conn.prepareStatement(sql); 
                        ps.setString(1,  "zhangsan"); 
                        ps.setString(2,  "111"); 
                         //设置二进制参数 
                        File file =  new File( "D:\\new\\dbtools\\src\\res\\PIC.PNG"); 
                        InputStream in =  new BufferedInputStream( new FileInputStream(file)); 
                        ps.setBinaryStream(3, in, ( int) file.length()); 
                        ps.executeUpdate(); 
                        in.close(); 
                }  catch (IOException e) { 
                        e.printStackTrace(); 
                }  catch (SQLException e) { 
                        e.printStackTrace(); 
                }  finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 

         public  static  void queryBlob() { 
                Connection conn = DBToolkit.getConnection(); 
                PreparedStatement ps =  null
                Statement stmt =  null
                ResultSet rs =  null
                 try { 
                        String sql =  "select pic from user where id = 24"
                        stmt = conn.createStatement(); 
                        rs = stmt.executeQuery(sql); 
                         if (rs.next()) { 
                                InputStream in = rs.getBinaryStream(1); 
                                File file =  new File( "D:\\new\\dbtools\\src\\res\\PIC_COPY.PNG"); 
                                OutputStream out =  new BufferedOutputStream( new FileOutputStream(file)); 
                                 byte[] buff =  new  byte[1024]; 
                                 for ( int i = 0; (i = in.read(buff)) > 0;) { 
                                        out.write(buff, 0, i); 
                                } 
                                out.flush(); 
                                out.close(); 
                                in.close(); 
                        } 
                        rs.close(); 
                        stmt.close(); 
                }  catch (IOException e) { 
                        e.printStackTrace(); 
                }  catch (SQLException e) { 
                        e.printStackTrace(); 
                }  finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 
}
 
注意,要确保二进制数据长度足够大,否则可能导致数据写入不完整的问题。
 
三、插入读取clob字段
 
clob在MySQL5中对应的就是text字段,可以根据实际需要选择合适的长度。
 
package lavasoft.jdbctest; 

import lavasoft.common.DBToolkit; 

import java.io.*; 
import java.sql.*; 

/** 
* 操作MySQL5的Clob字段 

* @author leizhimin 2009-12-3 13:56:16 
*/
 
public  class ClobTest { 
         public  static  void main(String[] args) { 
                insertClob(); 
                queryClob(); 
        } 

         public  static  void insertClob() { 
                Connection conn = DBToolkit.getConnection(); 
                PreparedStatement ps =  null
                 try { 
                        String sql =  "insert into testdb.user (name, pswd, remark) values (?, ?, ?)"
                        ps = conn.prepareStatement(sql); 
                        ps.setString(1,  "zhangsan"); 
                        ps.setString(2,  "111"); 
                         //设置二进制参数 
                        File file =  new File( "D:\\new\\dbtools\\src\\res\\PIC.PNG"); 
//                        InputStreamReader reader = new InputStreamReader(new FileInputStream("D:\\new\\dbtools\\src\\res\\TEXT.txt"),"GB18030"); 
                        InputStreamReader reader =  new InputStreamReader( new FileInputStream( "D:\\new\\dbtools\\src\\res\\TEXT.txt")); 
                        ps.setCharacterStream(3, reader, ( int) file.length()); 
                        ps.executeUpdate(); 
                        reader.close(); 
                }  catch (IOException e) { 
                        e.printStackTrace(); 
                }  catch (SQLException e) { 
                        e.printStackTrace(); 
                }  finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 

         public  static  void queryClob() { 
                Connection conn = DBToolkit.getConnection(); 
                PreparedStatement ps =  null
                Statement stmt =  null
                ResultSet rs =  null
                 try { 
                        String sql =  "select remark from user where id = 1"
                        stmt = conn.createStatement(); 
                        rs = stmt.executeQuery(sql); 
                         if (rs.next()) { 
                                Reader reader = rs.getCharacterStream(1); 
                                File file =  new File( "D:\\new\\dbtools\\src\\res\\TEXT_COPY.txt"); 
                                OutputStreamWriter writer =  new OutputStreamWriter( new FileOutputStream(file)); 
//                                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file),"ISO-8859-1"); 
//                                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file),"GB18030"); 
                                 char[] buff =  new  char[1024]; 
                                 for ( int i = 0; (i = reader.read(buff)) > 0;) { 
                                        writer.write(buff, 0, i); 
                                } 
                                writer.flush(); 
                                writer.close(); 
                                reader.close(); 
                        } 
                        rs.close(); 
                        stmt.close(); 
                }  catch (IOException e) { 
                        e.printStackTrace(); 
                }  catch (SQLException e) { 
                        e.printStackTrace(); 
                }  finally { 
                        DBToolkit.closeConnection(conn); 
                } 
        } 
}
 
在处理blob字段时候,由于直接处理的是二进制流,所以没啥问题。在处理clob字段的时候,由于数据库对clob是以字符的形式进行存储,这就有一个编码问题。本文虽然成功的插入读取了clob字段,但是还没有解决乱码问题,因为JDBC在获取到clob的时候,已经对其进行了编码,Reader reader = rs.getCharacterStream(1); 这就导致了编码的混乱,如果要彻底解决,还需要看看MySQL驱动的实现。通过非常规手段来解决。为了绕开此问题,可以将clob的数据存储为blog来操作,可以避免此问题。


本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/238222,如需转载请自行联系原作者
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
11月前
|
SQL 人工智能 关系型数据库
如何实现MySQL百万级数据的查询?
本文探讨了在MySQL中对百万级数据进行排序分页查询的优化策略。面对五百万条数据,传统的浅分页和深分页查询效率较低,尤其深分页因偏移量大导致性能显著下降。通过为排序字段添加索引、使用联合索引、手动回表等方法,有效提升了查询速度。最终建议根据业务需求选择合适方案:浅分页可加单列索引,深分页推荐联合索引或子查询优化,同时结合前端传递最后一条数据ID的方式实现高效翻页。
548 0
|
Java 数据库连接
【YashanDB知识库】JDBC驱动的date类型字段结果集调用getString方法只返回日期,不返回时分秒
【YashanDB知识库】JDBC驱动的date类型字段结果集调用getString方法只返回日期,不返回时分秒
|
10月前
|
存储 关系型数据库 MySQL
在CentOS 8.x上安装Percona Xtrabackup工具备份MySQL数据步骤。
以上就是在CentOS8.x上通过Perconaxtabbackup工具对Mysql进行高效率、高可靠性、无锁定影响地实现在线快速全量及增加式数据库资料保存与恢复流程。通过以上流程可以有效地将Mysql相关资料按需求完成定期或不定期地保存与灾难恢复需求。
725 10
|
11月前
|
SQL 存储 缓存
MySQL 如何高效可靠处理持久化数据
本文详细解析了 MySQL 的 SQL 执行流程、crash-safe 机制及性能优化策略。内容涵盖连接器、分析器、优化器、执行器与存储引擎的工作原理,深入探讨 redolog 与 binlog 的两阶段提交机制,并分析日志策略、组提交、脏页刷盘等关键性能优化手段,帮助提升数据库稳定性与执行效率。
285 0
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
570 28
|
12月前
|
关系型数据库 MySQL
MySQL数据表添加字段(三种方式)
本文解析了数据表的基本概念及字段添加方法。在数据表中,字段是纵向列结构,记录为横向行数据。MySQL通过`ALTER TABLE`指令支持三种字段添加方式:1) 末尾追加字段,直接使用`ADD`语句;2) 首列插入字段,通过`FIRST`关键字实现;3) 指定位置插入字段,利用`AFTER`指定目标字段。文内结合`student`表实例详细演示了每种方法的操作步骤与结构验证,便于理解与实践。
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
存储 SQL 缓存
mysql数据引擎有哪些
MySQL 提供了多种存储引擎,每种引擎都有其独特的特点和适用场景。以下是一些常见的 MySQL 存储引擎及其特点:
319 0
|
SQL 关系型数据库 MySQL
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
本文探讨了在使用YMP 23.2.1.3迁移MySQL Server字符集为latin1的中文数据至YashanDB时出现乱码的问题。问题根源在于MySQL latin1字符集存放的是实际utf8编码的数据,而YMP尚未支持此类场景。文章提供了两种解决方法:一是通过DBeaver直接迁移表数据;二是将MySQL表数据转换为Insert语句后手动插入YashanDB。同时指出,这两种方法适合单张表迁移,多表迁移可能存在兼容性问题,建议对问题表单独处理。
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB

推荐镜像

更多