Mybatis实现数据库的Json字符串转换为Java对象的方式


在工作中遇到数据库中,某些表的字段存的是Json字符串,取出来的时候需要反序列化为Java对象,特此记录。
主要借助TypeHandler来帮助实现。

一、反序列化Json对象

前提配置

表数据如下,最主要关注function字段,现在为Json对象,后面演示Json数组的方式
在这里插入图片描述

对应的Java类

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Permission{
    
    
  private int seq;
  private String title;
  private boolean countEnable;
}

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Code {
    
    
  private int id;
  private Permission function;
}

1.1 自定义类型处理器,继承BaseTypeHandler

@MappedJdbcTypes(JdbcType.VARCHAR) // 表明对应字段在数据库中的类型,也可以写在对应的SQL语句处
public class PermissionHandler extends BaseTypeHandler<Permission> {
    
    
  // 序列化工具,我这里用的Jackson,也可以用gson等,需要自己写
  private Serializer serializer = new Serializer();

  @Override
  public void setNonNullParameter(PreparedStatement preparedStatement, int i, Permission permission, JdbcType jdbcType) throws SQLException {
    
    
    preparedStatement.setString(i, serializer.encode(permission));
  }

  @Override
  public Permission getNullableResult(ResultSet resultSet, String s) throws SQLException {
    
    
    return serializer.decode(resultSet.getString(s), Permission.class);
  }

  @Override
  public Permission getNullableResult(ResultSet resultSet, int i) throws SQLException {
    
    
    return serializer.decode(resultSet.getString(i), Permission.class);
  }

  @Override
  public Permission getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
    
    
    return serializer.decode(callableStatement.getString(i), Permission.class);
  }

1.2 配置PermissionHandler

在Mybatis的配置文件中,需要声明自定义的处理器,否则会一直报错

org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in com/mediacomm/dao/IRegCodeDao.java (best guess)
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property 'function'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.

【注意】mybatis的配置文件中是有顺序要求的,如果configuration字段下出现了报错,就要看一下提示的内容,我就是因为typeHandlers的位置不对。

<configuration>
    ......
    <typeHandlers>
        <typeHandler handler="com.ccc.handler.PermissionHandler"/>
    </typeHandlers>
    ......
    <configuration>

1.3 SQL语句中声明字段类型

在对应的字段上,使用javaType声明字段的类型。
前面提到的@MappedJdbcTypes(JdbcType.VARCHAR),也可以不写,然后在此处用
jdbcType = JdbcType.VARCHAR声明

public interface IDao{
    
    
  @Select("select * from code")
  @Results(id = "codeMap",
          value = {
    
    
                  @Result(id = true, column = "id", property = "id"),
                  @Result(column = "function", property = "function", javaType = com.ccc.domain.Permission.class),
          })
  Code findAll();

二、反序列化Json数组

前提配置

表数据如下,function字段,现在为Json数组的方式
在这里插入图片描述

对应的Java类

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Permission{
    
    
  private int seq;
  private String title;
  private boolean countEnable;
}

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Code {
    
    
  private int id;
  private List<Permission> function;
}

2.1 自定义类型处理器,继承BaseTypeHandler

@MappedJdbcTypes(JdbcType.VARCHAR)
public class PermissionHandler extends BaseTypeHandler<List<Permission>> {
    
    
  private Serializer serializer = new LicenceSerializer();

  @SneakyThrows
  @Override
  public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<Permission> permission, JdbcType jdbcType) throws SQLException {
    
    
    preparedStatement.setString(i, serializer.encode(permission));
  }

  @SneakyThrows
  @Override
  public List<Permission> getNullableResult(ResultSet resultSet, String s) throws SQLException {
    
    
    // 使用Jackson解析Json数组的方式,并以集合的方式返回
    return serializer.decodeList(resultSet.getString(s), Permission.class);
  }

  @SneakyThrows
  @Override
  public List<Permission> getNullableResult(ResultSet resultSet, int i) throws SQLException {
    
    
    return serializer.decodeList(resultSet.getString(i), Permission.class);
  }

  @SneakyThrows
  @Override
  public List<Permission> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
    
    
    return serializer.decodeList(callableStatement.getString(i), Permission.class);
  }
}

2.2 配置PermissionHandler

同样的,在Mybatis的配置文件中,声明自定义的处理器

<configuration>
    ......
    <typeHandlers>
        <typeHandler handler="com.ccc.handler.PermissionHandler"/>
    </typeHandlers>
    ......
    <configuration>

2.3 SQL语句中声明字段类型

【注意】此处的javaType要用List而不再是Permission

public interface IDao{
    
    
  @Select("select * from code")
  @Results(id = "codeMap",
          value = {
    
    
                  @Result(id = true, column = "id", property = "id"),
                  @Result(column = "function", property = "function", javaType = java.util.List.class),
          })
  Code findAll();

二、测试结果

[Code(id=1,function=[Permission(seq=3, title=null, countEnable=false), Permission(seq=3, title=null, countEnable=false)])]```

猜你喜欢

转载自blog.csdn.net/weixin_42717117/article/details/128500096