PostgreSql MySQL数据库中插入或读取blob 、bytea 数据

一、PostgreSql

PostgreSql 中bytea 数据类型是二进制数据,可以用来存储图片或者其他的大文件格式,当bytea数据类型中存储少量字节的时候可以通过SQL语句进行CRUD 

数据库中的bytea是使用二进制进行按照字节存储

参考:https://www.postgresql.org/docs/9.2/static/datatype-binary.html

https://www.yiibai.com/manual/postgresql/datatype-binary.html   这里面的"\"写成了"/" 

写入数据:

要向数据中写入一个字节的数据,应该使用该字节的8进制进行写入

如:“}”的ASCII码为“125(10进制)” 对应的8进制为“175” 

注意:如果10进制转换为8进制没有三位的应该在前面补0

如:“=”的ASCII码为“61”对对应的8进制为“75” 应该写成‘\075’ 而不是‘\75’

所以向数据库中插入“}”的时候使用“\175” 在插入的时候每一个直接使用斜杠“\”隔开

update dj_data SET data_content='\175\175'::bytea where terminal_id='321'; 

如这样就设置值为了“}}”

 

如果不使用斜杠“\”表明里面的内容全部按照字符进行插入

如update dj_data SET data_content='175175'::bytea where terminal_id='321';实际上是设置值为字符的175175

在读取值的时候也是使用可以使用encode('字段','hex')将其显示转换成16进制的字符串进行查看

select encode(data_content,'hex'),data_content from dj_data where terminal_id='321';

如前面更新的值转换成16进制查看为7d7d,“16进制7d”为“10进制125”为“8进制175”为“字符}”

在Navicat中可以使用如下来查看bytea对饮的具体的字符串

本文属于自己一点总结,https://www.postgresql.org/docs/9.2/static/datatype-binary.html英文文档没有看太明白,有兴趣可以看看原因文参考

二、Mysql

使用unhex()函数将一对16进制的数转换为字符,应该说是转换为一个字节

使用hex()函数将一个字节转换为16进制的字符串

注意:上面说转为一个字节因为10进制的  0 到 31 以及 127 到 255是不可打印的,不能转换为字符,但在数据库中也能进行存储,因此使用字节而不是字符

如:“}”的ASCII码为“125(10进制)” 对应的16进制为“7d”

 UPDATE dj_data set data_content=unhex('7d')  where  terminal_id   = '123'; 

使用上面语句修改值为“}”

 UPDATE dj_data set data_content=unhex('7d7d')  where  terminal_id   = '123'; 

使用上面语句修改值为“}}”

注意:由于在unhex()里面没有明确区分字符的符号,因此每一个字节必须保证为两位确保能够正确解析成16进制

 UPDATE dj_data set data_content=unhex('44')  where  terminal_id   = '123'; 得到结果是 D 对应10进制AscII码为68

 UPDATE dj_data set data_content=unhex('0404')  where  terminal_id   = '123'; 得到结果是 对应10进制AscII码为4的两个字符

使用 hex()读取BLOB格式转为16进制的字符串

 

 

 

 

 

 

<think>我们正在讨论MyBatis中如何读取数据库BLOB字段。根据引用内容,MyBatis提供了BlobTypeHandler来处理Blob字段,通常将数据库Blob字段映射到Java的byte[]类型。下面我将详细说明实现步骤。 ### 1. 数据库表结构示例 假设我们有一个表,其中包含BLOB类型的字段: ```sql CREATE TABLE t_file ( id INT(12) NOT NULL AUTO_INCREMENT, content BLOB NOT NULL, -- BLOB字段 PRIMARY KEY (id) ); ``` ### 2. Java实体类 在Java中,对应的实体类应该将BLOB字段映射为`byte[]`类型: ```java public class FileEntity { private Long id; private byte[] content; // 对应BLOB字段 // 省略getter和setter } ``` ### 3. MyBatis映射文件配置 在MyBatis的Mapper XML文件中,我们需要为BLOB字段指定`BlobTypeHandler`: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.FileMapper"> <resultMap id="fileResultMap" type="FileEntity"> <id column="id" property="id" /> <result column="content" property="content" typeHandler="org.apache.ibatis.type.BlobTypeHandler"/> </resultMap> <!-- 根据ID查询文件 --> <select id="getFileById" resultMap="fileResultMap"> SELECT id, content FROM t_file WHERE id = #{id} </select> <!-- 插入文件 --> <insert id="insertFile" parameterType="FileEntity"> INSERT INTO t_file (content) VALUES (#{content, typeHandler=org.apache.ibatis.type.BlobTypeHandler}) </insert> </mapper> ``` ### 4. Mapper接口 ```java public interface FileMapper { FileEntity getFileById(Long id); int insertFile(FileEntity file); } ``` ### 5. 使用示例 #### 插入BLOB数据 ```java // 获取文件字节数组 byte[] fileContent = ...; // 例如从MultipartFile获取 FileEntity file = new FileEntity(); file.setContent(fileContent); fileMapper.insertFile(file); ``` #### 读取BLOB数据 ```java FileEntity file = fileMapper.getFileById(1L); byte[] content = file.getContent(); // 获取BLOB数据 ``` ### 6. 注意事项 1. **大文件处理**:对于非常大的BLOB数据(如超过100MB),建议使用流式处理以避免内存溢出。MyBatis提供了`ResultHandler`和`@Options`注解的`fetchSize`参数来支持流式读取[^1]。 2. **数据库配置**:确保数据库连接允许传输大对象(如MySQL的`max_allowed_packet`配置)。 3. **类型处理器**:MyBatis默认已经注册了`BlobTypeHandler`,因此如果字段类型是`byte[]`,且数据库字段是BLOB,通常可以省略`typeHandler`的显式指定。但在某些情况下(如Oracle的BLOB类型),可能需要显式配置。 ### 7. 流式读取BLOB 为了避免内存溢出,我们可以使用流式读取: ```java @Select("SELECT content FROM t_file WHERE id = #{id}") @Options(fetchSize = Integer.MIN_VALUE) // 启用流式读取 @ResultType(byte[].class) void getFileContentStream(Long id, ResultHandler<byte[]> handler); ``` 在调用时: ```java fileMapper.getFileContentStream(1L, context -> { byte[] chunk = context.getResultObject(); // 处理数据块 }); ``` ### 8. 不同数据库BLOB类型 - **MySQL**:支持`BLOB`, `LONGBLOB`等类型,映射到`byte[]`即可。 - **Oracle**:使用`BLOB`类型,但需要特殊处理,可能需要使用`oracle.sql.BLOB`类型和`OracleBlobTypeHandler`(自定义第三方提供)。 - **PostgreSQL**:使用`bytea`类型,可以直接映射到`byte[]`,使用`ByteArrayTypeHandler`。 ### 常见问题解决 - **问题:读取BLOB字段返回null** 解决方案:检查是否在`resultMap`中正确配置了`typeHandler`,并确保数据库字段类型正确[^2]。 - **问题:插入大文件时报错(如Packet too large)** 解决方案:增加MySQL的`max_allowed_packet`配置(如设置为1GB)[^3]。 ### 性能优化建议 1. 对于大于10MB的文件,使用流式读取和写入。 2. 避免在事务中处理大BLOB,以减少数据库连接占用时间。 3. 考虑将大文件存储在文件系统中,数据库中只存储路径。 --- ### 相关问题 1. MyBatis如何处理Oracle的BLOB字段? 2. 如何实现MyBatis流式读取大文件? 3. 如何解决MySQL插入BLOB时出现的“Packet too large”错误? 4. MyBatis中除了BlobTypeHandler,还有哪些处理二进制数据的TypeHandler? 5. 如何在MyBatis中实现BLOB字段的分块读取? 6. MyBatis和Spring Data JPA处理BLOB字段的主要区别是什么?</think>### MyBatis 读取数据库 BLOB 字段的完整实现 在 MyBatis 中处理 BLOB 字段的核心是使用 `BlobTypeHandler`,它负责将数据库BLOB 类型与 Java 的 `byte[]` 类型进行转换。以下是详细实现步骤: #### 1. 数据库表结构 ```sql CREATE TABLE t_file ( id INT(12) NOT NULL AUTO_INCREMENT, content BLOB NOT NULL, -- BLOB字段 PRIMARY KEY(id) ); ``` #### 2. Java 实体类 ```java public class FileEntity { private Long id; private byte[] content; // 使用byte[]类型映射BLOB字段 // 省略getter/setter } ``` #### 3. MyBatis 映射文件配置 ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.FileMapper"> <!-- 结果映射配置 --> <resultMap id="fileResultMap" type="FileEntity"> <id column="id" property="id" /> <!-- 关键配置:为BLOB字段指定TypeHandler --> <result column="content" property="content" typeHandler="org.apache.ibatis.type.BlobTypeHandler"/> </resultMap> <!-- 查询操作 --> <select id="getFileById" resultMap="fileResultMap"> SELECT id, content FROM t_file WHERE id = #{id} </select> <!-- 插入操作 --> <insert id="insertFile" parameterType="FileEntity"> INSERT INTO t_file (content) VALUES (#{content, typeHandler=org.apache.ibatis.type.BlobTypeHandler}) </insert> </mapper> ``` #### 4. Mapper 接口 ```java public interface FileMapper { FileEntity getFileById(Long id); int insertFile(FileEntity file); } ``` #### 5. 服务层实现 ```java @Service public class FileService { private final FileMapper fileMapper; // 保存文件 public void saveFile(MultipartFile file) throws IOException { FileEntity entity = new FileEntity(); entity.setContent(file.getBytes()); // 转换为byte[] fileMapper.insertFile(entity); } // 读取文件 public byte[] getFileContent(Long id) { return fileMapper.getFileById(id).getContent(); } // 流式下载(大文件优化) public void downloadFile(Long id, OutputStream outputStream) throws IOException { byte[] data = getFileContent(id); try (ByteArrayInputStream bis = new ByteArrayInputStream(data)) { bis.transferTo(outputStream); } } } ``` #### 6. 控制器示例 ```java @RestController @RequestMapping("/files") public class FileController { private final FileService fileService; // 文件下载 @GetMapping("/download/{id}") public void downloadFile(@PathVariable Long id, HttpServletResponse response) throws IOException { // 设置响应头 response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=file_" + id); // 流式输出 fileService.downloadFile(id, response.getOutputStream()); } } ``` ### 关键配置说明 1. **TypeHandler 选择**: - `BlobTypeHandler`:标准BLOB处理(推荐) - `ByteArrayTypeHandler`:直接二进制处理(适用于小文件) 2. **大文件处理优化**: ```java // 分块读取(避免OOM) private static final int BUFFER_SIZE = 4096; public void streamLargeFile(Long id, OutputStream os) throws IOException { byte[] data = getFileContent(id); int offset = 0; while (offset < data.length) { int chunkSize = Math.min(BUFFER_SIZE, data.length - offset); os.write(data, offset, chunkSize); offset += chunkSize; } } ``` ### 不同数据库的适配方案 | 数据库 | 配置要点 | |------------|--------------------------------------------------------------------------| | **MySQL** | 默认支持,使用`BLOB`/`LONGBLOB`类型 | | **Oracle** | 需使用`BLOB`类型,可能需要自定义`OracleBlobTypeHandler` | | **H2** | 使用`BLOB`类型,测试时需初始化`SET BINARY_LARGE_OBJECT_BUFFER_SIZE` | ### 常见问题解决方案 1. **BLOB字段返回null**: - 确保在`resultMap`中正确配置`typeHandler` - 检查数据库连接配置(如MySQL的`allowLoadLocalInfile=true`) 2. **大文件内存溢出**: ```java // 使用流式ResultHandler @Select("SELECT content FROM t_file WHERE id = #{id}") @Options(fetchSize = Integer.MIN_VALUE) // 启用流式模式 void getFileStream(Long id, ResultHandler<byte[]> handler); ``` 3. **插入性能优化**: ```xml <!-- 批量插入配置 --> <insert id="batchInsert" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_file (content) VALUES <foreach collection="list" item="item" separator=","> (#{item.content, typeHandler=org.apache.ibatis.type.BlobTypeHandler}) </foreach> </insert> ``` ### 性能优化建议 1. 超过10MB的文件使用流式传输 2. 添加数据库连接池配置: ```properties # MySQL配置 max_allowed_packet=256M wait_timeout=600 ``` 3. 启用MyBatis二级缓存: ```xml <cache eviction="LRU" size="1024"/> ``` > **核心要点**:始终使用`byte[]`类型映射BLOB字段,通过`BlobTypeHandler`实现类型转换,对大文件采用流式处理避免内存溢出[^1][^2][^3]。 --- ### 相关问题 1. MyBatis如何处理Oracle的BLOB字段? 2. 如何实现MyBatis流式读取大文件? 3. 如何解决MySQL插入BLOB时出现的“Packet too large”错误? 4. MyBatis中除了BlobTypeHandler,还有哪些处理二进制数据的TypeHandler? 5. 如何在MyBatis中实现BLOB字段的分块读取? 6. MyBatis和Spring Data JPA处理BLOB字段的主要区别是什么?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值