写点什么

利用 mybatis 的 typeHandler 解决手动拆分拼接数据的麻烦

作者:六哥是全栈
  • 2024-12-04
    广西
  • 本文字数:2436 字

    阅读完需:约 8 分钟

引言

在现代的 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


发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2024-08-28 加入

还未添加个人简介

评论

发布
暂无评论
利用mybatis的typeHandler解决手动拆分拼接数据的麻烦_mybatis_六哥是全栈_InfoQ写作社区