👨🏻💻 热爱摄影的程序员
👨🏻🎨 喜欢编码的设计师
🧕🏻 擅长设计的剪辑师
🧑🏻🏫 一位高冷无情的全栈工程师
欢迎分享 / 收藏 / 赞 / 在看!
已知在 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 类型的字段了: