MyBatis--自定义TypeHandler处理枚举

绝地灬酷狼 2021-08-13 19:02 549阅读 0赞

自定义TypeHandler处理枚举

在绝大多数情况下,typeHandler 因为枚举而使用,MyBatis 已经定义了两个类作为枚举类型的支持,这两个类分别是:

  • EnumOrdinalTypeHandler。
  • EnumTypeHandler。

示例:
创建一个性别枚举类:SexEnum

  1. package com.mybatis.po;
  2. public enum SexEnum {
  3. MALE(1, "男"),
  4. FEMALE(0, "女");
  5. private int id;
  6. private String name;
  7. /** stter and getter **/
  8. SexEnum(int id, String name) {
  9. this.id = id;
  10. this.name = name;
  11. }
  12. public SexEnum getSexById(int id) {
  13. for (SexEnum sex : SexEnum.values()) {
  14. if (sex.getId() == id) {
  15. return sex;
  16. }
  17. }
  18. return null;
  19. }
  20. }

创建一个myUser表:

  1. CREATE TABLE `myuser` (
  2. `id` bigint(20) NOT NULL,
  3. `user_name` varchar(20) DEFAULT NULL,
  4. `password` varchar(20) DEFAULT NULL,
  5. `sex` char(1) DEFAULT NULL,
  6. `mobile` varchar(20) DEFAULT NULL,
  7. `tel` varchar(20) DEFAULT NULL,
  8. `email` varchar(20) DEFAULT NULL,
  9. `note` varchar(20) DEFAULT NULL,
  10. PRIMARY KEY (`id`)
  11. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

再创建一个用户POJO:

  1. public class User {
  2. private Long id;
  3. private String userName;
  4. private String password;
  5. private SexWnum sex;
  6. private String moblie;
  7. private String tel;
  8. private String email;
  9. private String note;
  10. /**setter and getter**/
  11. }

EnumOrdinalTypeHandler

EnumOrdinalTypeHandler 是按 MyBatis 根据枚举数组下标索引的方式进行匹配的,也是枚举类型的默认转换类,它要求数据库返回一个整数作为其下标,它会根据下标找到对应的枚举类型。

根据这条规则,创建一个UserMapper.xml作为测试的例子:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.mybatis.mapper.UserMapper">
  4. <resultMap id="userMapper" type="user">
  5. <result property="id" column="id" />
  6. <result property="userName" column="user_name" />
  7. <result property="password" column="passsword" />
  8. <result property="sex" column="sex" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
  9. <result property="mobile" column="mobile" />
  10. <result property="tel" column="tel" />
  11. <result property="email" column="email" />
  12. <result property="note" column="note" />
  13. </resultMap>
  14. <select id="getUser" resultMap="userMapper" parameterType="long">
  15. select id,user_name,password,sex,mobile,tel,email,note from myUser
  16. where id=#{id}
  17. </select>
  18. </mapper>

插入一条数据,执行的 SQL 如下:

  1. INSERT INTO `myuser` (`id`,`user_name`,`password`,`sex`,`mobile`,`tel`,`email`,`note`) VALUES(1,'zhangsan','123456','1','13675683675','0755-88888888','zhangsan@163.com','note...

这样,sex 字段就在数据库里被设置为 1,代表女性,使用以下进行测试。

  1. package com.mybatis.test;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.apache.log4j.Logger;
  9. import com.mybatis.mapper.UserMapper;
  10. import com.mybatis.po.User;
  11. public class MyBatisTest {
  12. public static void main(String[] args) throws IOException {
  13. Logger log = Logger.getLogger(MyBatisTest.class);
  14. InputStream config = Resources
  15. .getResourceAsStream("mybatis-config.xml");
  16. SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
  17. SqlSession ss = ssf.openSession();
  18. UserMapper userMapper = ss.getMapper(UserMapper.class);
  19. User user = userMapper.getUser(1L);
  20. log.info(user.getSex().getName());
  21. }
  22. }

运行结果:
format_png

EnumTypeHandler

EnumTypeHandler 会把使用的名称转化为对应的枚举,比如它会根据数据库返回的字符串“MALE”,进行 Enum.valueOf(SexEnum.class,“MALE”);转换,所以为了测试 EnumTypeHandler 的转换,我们把数据库的 sex 字段修改为字符型(varchar(10)),并把 sex=1 的数据修改为 FEMALE,于是可以执行以下 SQL。

  1. ALTER TABLE myUser MODIFY sex VARCHAR(10);
  2. UPDATE myUser SET sex='FEMALE' WHERE SEX = 1;

然后使用 EnumTypeHandler 修改 UserMaperr.xml,代码如下所示。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.mybatis.mapper.UserMapper">
  4. <resultMap id="userMapper" type="com.mybatis.po.User">
  5. <result property="id" column="id" />
  6. <result property="userName" column="user_name" />
  7. <result property="password" column="passsword" />
  8. <result property="sex" column="sex" typeHandler="org.apache.ibatis.type.EnumTypeHandler" />
  9. <result property="mobile" column="mobile" />
  10. <result property="tel" column="tel" />
  11. <result property="email" column="email" />
  12. <result property="note" column="note" />
  13. </resultMap>
  14. <select id="getUser" resultMap="userMapper" parameterType="long">
  15. select id,user_name,password,sex,mobile,tel,email,note from myUser
  16. where id=#{id}
  17. </select>
  18. </mapper>

自定义枚举typeHandler

我们已经讨论了 MyBatis 内部提供的两种转换的 typeHandler,但是它们有很大的局限性,更多的时候我们希望使用自定义的 typeHandler。执行下面的 SQL,把数据库的 sex 字段修改为整数型。

  1. UPDATE myUser SET sex='0' WHERE sex = 'FEMALE';
  2. UPDATE myUser SET sex='1' WHERE sex = 'MALE';
  3. ALTER TABLE myUser MODIFY sex INT(10);

此时,按 SexEnum 的定义,sex=1 为男性,sex=0 为女性。为了满足这个规则,让我们自定义一个 SexEnumTypeHandler,如下所示。

  1. package com.mybatis.test;
  2. import java.sql.CallableStatement;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import org.apache.ibatis.type.JdbcType;
  7. import org.apache.ibatis.type.MappedJdbcTypes;
  8. import org.apache.ibatis.type.MappedTypes;
  9. import org.apache.ibatis.type.TypeHandler;
  10. import com.mybatis.po.SexEnum;
  11. @MappedTypes(SexEnum.class)
  12. @MappedJdbcTypes(JdbcType.INTEGER)
  13. public class SexEnumTypeHandler implements TypeHandler<SexEnum> {
  14. @Override
  15. public void setParameter(PreparedStatement ps, int i, SexEnum parameter,
  16. JdbcType jdbcType) throws SQLException {
  17. ps.setInt(i, parameter.getId());
  18. }
  19. @Override
  20. public SexEnum getResult(ResultSet rs, String columnName)
  21. throws SQLException {
  22. int id = rs.getInt(columnName);
  23. return SexEnum.getSexById(id);
  24. }
  25. @Override
  26. public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
  27. int id = rs.getInt(columnIndex);
  28. return SexEnum.getSexById(id);
  29. }
  30. @Override
  31. public SexEnum getResult(CallableStatement rs, int columnIndex)
  32. throws SQLException {
  33. int id = rs.getInt(columnIndex);
  34. return SexEnum.getSexById(id);
  35. }
  36. }

将 UserMapper.xml 的 typeHandler 换成自定义的 SexEnumTypeHandler,运行程序就可以得到我们想要的结果。

发表评论

表情:
评论列表 (有 0 条评论,549人围观)

还没有评论,来说两句吧...

相关阅读