👨🏻💻 热爱摄影的程序员
👨🏻🎨 喜欢编码的设计师
🧕🏻 擅长设计的剪辑师
🧑🏻🏫 一位高冷无情的全栈工程师
欢迎分享 / 收藏 / 赞 / 在看!
已知在 MySQL 中有表 test_json_type,定义如下:
-- 测试JsonType drop table if exists test_json_type; create table test_json_type ( test_id bigint not null primary key comment 'testID', ids json not null comment 'ids', ) engine innodb comment '测试JsonType表';
复制
在 MyBatis-Plus 中,可以通过实现 TypeHandler 接口来创建自定义的类型处理器,用于处理 Java 类型和 JDBC 类型之间的转换。
为了处理 JSON 字符串和 Java 数组之间的转换,创建一个名为 JsonTypeHandler 的类,并实现 TypeHandler 接口,将 Java 中的字符串数组转换为 JSON 字符串存储到 MySQL 数据库中,以及将数据库中的 JSON 字符串转换回 Java 字符串数组。
MyBatis-Plus 官网-字段类型处理器
首先,需要添加 Jackson 库到项目中,因为我们将使用它来序列化和反序列化 JSON:
<!-- 添加Jackson依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> </dependency>
复制
然后,创建 JsonTypeHandler 类。使用 Jackson 库的 ObjectMapper 来执行 JSON 序列化和反序列化。setNonNullParameter 方法用于将 Java 数组转换为 JSON 字符串并设置到 PreparedStatement 中,而 getNullableResult 方法用于从 ResultSet 或 CallableStatement 中检索 JSON 字符串并转换回 Java 数组:
public class JsonTypeHandler<T> extends BaseTypeHandler<T> { private static final ObjectMapper objectMapper = new ObjectMapper(); @Override public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { try { if (parameter instanceof String[]) { String json = objectMapper.writeValueAsString((String[]) parameter); ps.setString(i, json); } else { throw new IllegalArgumentException("Cannot convert type " + parameter.getClass().getName() + " to JSON"); } } catch (JsonProcessingException e) { throw new RuntimeException("Error converting to JSON", e); } } @Override public T getNullableResult(ResultSet rs, String columnName) throws SQLException { String json = rs.getString(columnName); if (json != null) { try { return (T) objectMapper.readValue(json, String[].class); } catch (IOException e) { throw new RuntimeException("Error converting JSON to type", e); } } return null; } @Override public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String json = rs.getString(columnIndex); if (json != null) { try { return (T) objectMapper.readValue(json, String[].class); } catch (IOException e) { throw new RuntimeException("Error converting JSON to type", e); } } return null; } @Override public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String json = cs.getString(columnIndex); if (json != null) { try { return (T) objectMapper.readValue(json, String[].class); } catch (IOException e) { throw new RuntimeException("Error converting JSON to type", e); } } return null; } }
复制
接下来,需要在 MyBatis 的映射文件或注解中指定使用这个自定义的类型处理器。如果使用 XML 映射文件,可以这样做:
<resultMap id="productResultMap" type="com.example.Product"> <id column="id" property="id"/> <result column="spec_ids" property="specIds" typeHandler="com.example.JsonTypeHandler"/> <!-- 其他字段映射 --> </resultMap>
复制
如果使用注解,需在实体类开启映射 autoResultMap = true 并且在字段上使用 @TypeHandler 注解:
@Data @EqualsAndHashCode(callSuper = true) @TableName(value = "test_json_type", autoResultMap = true) public class TestJsonType extends BaseEntity { @Serial private static final long serialVersionUID = 1L; /** * testID */ @TableId(value = "test_id") private Long testId; /** * ids */ @TableField(value = "ids", typeHandler = JsonTypeHandler.class) private String[] ids; }
复制
然后就可以正常地存取 JSON 类型的字段了: