springboot——typeHandler的使用

  1. 使用场景

typeHandler,类型转换器,就是将数据库中的类型与Java中的类型进行相互转换的处理器。

有时候,我们进行存储时的字段类型和数据库最终存储的字段类型是不一致的:比如我们在springboot传入的是一个list,而在数据库中需要以VARCHAR类型保存;又比如我们在springboot传入一个JSON类型,而数据库中以String类型存储该字段;或者说数据库中是JSON类型,但java无找不到对应的JSON类型(直接使用JSONObject会报错),也可以使用typeHandler。

一般情况,我们可以强转String再存储该字段,但有时候查询数据时会出现问题:较为典型的是String类型的JSON串数据,以String类型返回至前端时,会由于进行两次json解析,导致返回结果反斜杆:

而这会导致前端解析时出错,所以我们需要用typeHandler对其进行转换:

简而言之,typeHandler就是当springboot后端实体类中字段类型和数据库中字段类型不一致时进行使用。

2. mybatis下使用typeHandler

首先,我们需要编写一个typeHandler(以JSON转VARCHAR为例):

@MappedTypes(JSONObject.class)
@MappedJdbcTypes(JdbcType.LONGVARCHAR)
public class JsonObjectTypeHandler extends BaseTypeHandler<JSONObject> {

    /**
     * 插入数据时,将JSONObject转String
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSONObject.toJSONString(parameter));
    }

    /**
     * 根据列名,获取可以为空的结果
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    /**
     * 根据列索引,获取可以为空的结果
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getString(columnIndex);
        if (null != sqlJson){
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }
}

注意,该typeHandler需要放在mapper文件夹下(即和mapper类放在一起,否则会找不到)

然后,在mapper.xml文件中,编写resultmap映射字段,并指定哪些字段需要使用typeHandler:

<!--字段映射,将数据库中String类型的json串映射为JSONObject,避免返回前段时两次序列化使得返回结果带反斜杠-->
    <resultMap id="illnessMap" type="com.seven.springcloud.dto.IllnessDTO">
        <result column="Weight" property="Weight" javaType="com.alibaba.fastjson.JSONObject" jdbcType="VARCHAR"
                typeHandler="com.seven.springcloud.mapper.JsonObjectTypeHandler"/>
        <result column="Add_date" property="Drug_Date"/>
    </resultMap>
    <!--查询所有病人的信息-->
    <select id="selectUserIllness" resultMap="illnessMap">
        select * from user_illness where Account=#{Account}
    </select>

然后,实体类中,将字段类型设为JSONObject:

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)     //空值不返回
public class IllnessDTO implements Serializable {
    private JSONObject Weight;
    private String Drug_Date;
}

然后,就可以成功映射数据啦。

查看数据库,保存的是一个String类型的JSON串:

3. mybatis plus下使用typeHandler

使用mybatis plus时,我们也可以使用mybatis的方式,xml文件中编写resultMap的形式映射字段;也可以选择以mybatis plus的注解的形式使用。

首先,我们仍然需要编写一个typeHandler类:

@MappedJdbcTypes(JdbcType.VARCHAR)  //数据库类型
@MappedTypes({JSONObject.class})          //java数据类型
public class JsonTypeHandler implements TypeHandler<JSONObject> {
    @Override
    public void setParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
        if (parameter!=null){
            ps.setString(i, JSONObject.toJSONString(parameter));
        }

    }

    @Override
    public JSONObject getResult(ResultSet rs, String columnName) throws SQLException {
        return JSONObject.parseObject(rs.getString(columnName));
    }

    @Override
    public JSONObject getResult(ResultSet rs, int columnIndex) throws SQLException {
        return JSONObject.parseObject(rs.getString(columnIndex));
    }

    @Override
    public JSONObject getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return JSONObject.parseObject(cs.getString(columnIndex));
    }
}

注:我们需要再application.yml文件中指定该typeHandler所在的包的位置,否则会找不到:

mybatis-plus:
  type-handlers-package: com.seven.demo.typerHandler

然后,我们在实体类进行配置即可:

@TableName(value ="student",autoResultMap = true)    //autoResultMap为true才会自动配置resultMap映射字段
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {

    @TableId
    private Long id;

    private String name;

    @TableField(value = "grade", typeHandler = JsonTypeHandler.class)    //指定typeHandler进行转换类型
    private JSONObject grade;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

然后,我们就可以对类型进行转换了。

下面我们可以编写接口测试一下:

@RestController
public class StudentController {
    @Resource
    private StudentService studentService;

    @PostMapping("/add")
    public boolean add(@RequestBody Student student){
        return studentService.save(student);
    }

    @GetMapping("/get")
    public Student get(@RequestParam("id")int id){
        return studentService.getById(id);
    }
}

测试成功,查看数据库:

成功保存字符类型json串。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一款开源的Java开发框架,可以简化Spring应用程序的开发过程。MyBatis Plus是在MyBatis框架基础上的增强版本,为开发者提供了更便捷的CRUD操作接口和其他实用功能。PostgreSQL是一种开源的关系型数据库管理系统。 在Spring Boot项目中使用MyBatis Plus框架,可以通过添加相应的依赖和配置,快速集成MyBatis Plus。对于PostgreSQL数据库的支持,可以通过引入PostgreSQL的JDBC驱动来实现。 在使用MyBatis Plus与PostgreSQL时,可能会遇到类型转换的问题。例如,某些特定的数据类型在Java和PostgreSQL之间存在差异,需要通过类型处理器(TypeHandler)进行转换。 TypeHandlerMyBatis Plus中是用于处理Java对象与数据库列之间的类型转换的组件。当在实体类中定义了需要特殊处理的属性时,可以通过自定义TypeHandler来实现转换逻辑。在处理与PostgreSQL相关的类型时,可以使用MyBatis Plus提供的内置TypeHandler或自定义TypeHandler。 自定义TypeHandler通常需要实现TypeHandler接口,并指定Java对象与数据库类型的映射关系。在转换过程中,可以使用PostgreSQL JDBC驱动提供的各种方法来处理特定类型的转换逻辑。 在Spring Boot中配置TypeHandler通常需要在MyBatis的配置文件或配置类中进行相关配置。通过指定要使用TypeHandler和映射关系,可以实现Java对象与PostgreSQL类型的正确转换。 总之,使用Spring BootMyBatis Plus和PostgreSQL可以快速构建Java应用程序,并通过TypeHandler来处理类型转换问题,实现Java对象与PostgreSQL数据库之间的无缝集成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值