引言
在现代的 Web 开发中,我们经常需要处理各种类型的数据转换问题。特别是在使用数据库时,常常会遇到需要将数据库中的字符串字段与 Java 对象之间的复杂转换。例如,将逗号分隔的标签列表存储为单个字符串,并在应用层将其转换为 List<String>。这种情况下,手动进行数据的拆分和拼接不仅繁琐,而且容易出错。幸运的是,MyBatis 提供了 TypeHandler 机制,可以帮助我们简化这一过程。
什么是 TypeHandler
TypeHandler 是 MyBatis 中的一个接口,用于定义如何将 Java 类型转换为数据库类型,以及如何将数据库类型转换回 Java 类型。通过自定义 TypeHandler,我们可以实现更加灵活和高效的数据处理逻辑。
实操
假设我们有一个用户表 user,其中包含一个字段 tagIds 用于存储用户的兴趣标签 id,以逗号分隔的字符串形式存储。我们需要将这个字符串与 Java 中的 List<Long> 之间进行转换。
第一步(定义)
创建一个实现 TypeHandler 接口的用来处理数据库逗号连接的字符串和 java 中 List<Long> 之间的转换,只要是这种情况都可以使用,无需重复定义多个实现类
/**
* varchar to List<Long>
* @author luguoxiang
* 开源项目:https://gitee.com/lgx1992/lg-soar 求star!请给我star!请帮我点个star!
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class LongListTypeHandler implements TypeHandler<List<Long>> {
private final static String joiner = ",";
@Override
public void setParameter(PreparedStatement preparedStatement, int i, List<Long> longs, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, String.join(joiner, longs));
}
@Override
public List<Long> getResult(ResultSet resultSet, String s) throws SQLException {
String vs = resultSet.getString(s);
return vs == null ? null : Arrays.stream(vs.split(joiner)).map(Long::parseLong)
.collect(Collectors.toList());
}
@Override
public List<Long> getResult(ResultSet resultSet, int i) throws SQLException {
String vs = resultSet.getString(i);
return vs == null ? null : Arrays.stream(vs.split(joiner)).map(Long::parseLong)
.collect(Collectors.toList());
}
@Override
public List<Long> getResult(CallableStatement callableStatement, int i) throws SQLException {
String vs = callableStatement.getString(i);
return vs == null ? null : Arrays.stream(vs.split(joiner)).map(Long::parseLong)
.collect(Collectors.toList());
}
}
复制代码
第二步(使用)
上一步定义好了数据库 varchar 类型到 java List<Long> 的类型处理器,接下来我们该在业务开发中使用它了。
在 mybatis-plus 的 @TableField 中使用
mp 实体类中只需 @TableField(typeHandler = LongListTypeHandler.class) 标记字段即可,注意实体类上的 @TableName 必须设置 autoResultMap = true
/**
* @author luguoxiang
* @Date: 2024/8/23 17:22
* 开源项目:https://gitee.com/lgx1992/lg-soar 求star!请给我star!请帮我点个star!
*/
@TableName(value = "user", autoResultMap = true)
public class User {
private Long id;
private String username;
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> tagIds;
}
复制代码
在 xml 中使用
在 xml 需使用 resultMap 定义映射
<mapper namespace="com.example.mapper.UserMapper">
<!-- 使用 typeHandler -->
<resultMap id="BaseResultMap" type="com.example.model.User">
<id column="id" property="id" />
<result column="username" property="username" />
<result column="tag_ids" property="tagIds" typeHandler="com.example.LongListTypeHandler" />
</resultMap>
<select id="selectUserById" resultMap="BaseResultMap">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="com.example.model.User">
INSERT INTO user (name, tags) VALUES (#{name}, #{tag_ids, typeHandler=com.example.LongListTypeHandler})
</insert>
</mapper>
复制代码
结论
通过使用 MyBatis 的 TypeHandler 机制,我们可以非常方便地处理数据库字段与 Java 对象之间的复杂转换问题。在本例中,我们创建了一个自定义的 LongListTypeHandler,用于将逗号分隔的字符串转换为 List<Long>,并在实体类和映射文件中进行了相应的配置。这种方式不仅简化了代码,还提高了开发效率和代码的可维护性。
通过这种方式,你可以避免手动拆分和拼接数据带来的繁琐操作,使代码更加简洁和易于理解。同时,这种做法也使得数据处理逻辑更加集中和统一,便于后续的维护和扩展。
尾声
在现代 Web 开发中,数据转换是一个常见的需求。MyBatis 提供的 TypeHandler 机制为我们提供了一种高效、灵活的方式来处理这些转换问题。希望本文能帮助你在实际项目中更好地利用这一功能,提高开发效率和代码质量。
如果你对 MyBatis 和 MyBatis-Plus 有更多的兴趣,或者想要了解更多关于前后端开发的最佳实践,欢迎关注我们的微信公众号。我们会定期分享更多实用的技术文章和开发经验。
本文代码来源六哥开源前后端框架 lg-soar,如果您觉得对您有所帮助欢迎访问 https://gitee.com/lgx1992/lg-soar 给 lg-soar 一个 star
评论