mybatis & JPA 实体类型属性转换

1.写在前面:

      资料来自互联网,在此只是做一个汇总备忘,在做公司JAP数据脱敏,加解密用到了,就想如果是mybatis该怎么做方便,这里就找资料做一下备忘。

2.JAP  转换: 

在java JPA注解中,有个@Convert注解,其中需要传入一个Class作为convert参数,该class需要实现AttributeConverter<X,Y>接口。下面来看看AttributeConverter接口的作用。

AttributeConverter<X,Y>

实体属性类型转换器。主要使用场景:

  • 持久化enum
  • 加解密数据
  • 持久化日期

代码中数据类型,到数据库中类型,可能不一致或者需要做一个修饰转换,JPA里需要实现 AttributeConverter<X,Y>该接口中现两个方法:

  • y convertToDatabaseColumn(x) 作用:将实体属性x转化为y存储到数据库中,即插入和更新操作时执行;
  • x convertToEntityAttribute(y) 作用:将数据库中的字段y转化为实体属性x,即查询操作时执行。

例如 :实体枚举类型到数据库种类型的相互转换:

@Entity

@Table(name = "t_demo")

public class DemoEntity {

    @Convert(converter = StatusAttributeConverter.class)

    private String status; //状态:1 启用,-1 禁用,-2 已删除

}


//-----------------------------------------------
public class StatusAttributeConverter implements AttributeConverter<String, Integer> {

 

    @Override

    public Integer convertToDatabaseColumn(String status) {

        try {

            return Integer.parseInt(status);    //如果是数字,则直接返回(这里可以遍历StatusEnum的value来进一步验证)

        } catch (NumberFormatException e) {

            for (StatusEnum type : StatusEnum.values()) {    //如果不是数字,则通过StatusEnum来找到描述对应的数字

                if (status.equals(type.getDescription())) {

                    return type.getValue();

                }

            }

        }

        throw new RuntimeException("Unknown StatusEnum: " + status);    //如果StatusEnum里不存在代表数字或描述,则抛出异常

    }

 

    @Override

    public String convertToEntityAttribute(Integer value) {

        for (StatusEnum type : StatusEnum.values()) {    //将数字转换为描述

            if (value.equals(type.getValue())) {

                return type.getDescription();

            }

        }

        throw new RuntimeException("Unknown database value: " + value);

    }

}
//-----------------------------------------------
public enum StatusEnum {

    ENABLE(1, "启用"), DISABLE(-1, "禁用"), DELETED(-2, "已删除");

 

    StatusEnum(Integer value, String description) {

        this.value = value;

        this.description = description;

    }

}

 

3.mybatis 字段类型转换 

调研发现,有两种套路可寻,使用mybatis的拦截插件和自定义TypeHandler,这里先介绍TypeHandler的方式,需要自己代码实践验证。摘自:https://blog.csdn.net/acm_lkl/article/details/78609341

  • TypeHandler接口方式

    首先实现 TypeHandler 接口里面 getXXX,setXXX 方法,注意实现类上面的注解:@MappedJdbcTypes,@MappedTypes,MappedJdbcTypes是配置jdbc类型,这里的Jdbc类型必须org.apache.ibatis.type.JdbcType中的枚举类型, MappedTypes定义的是需要被拦截的java类型,TypeHandler T泛型,是传入的java类型。

例如:

package com.sankuai.lkl.typeHandler;

import com.sun.deploy.util.StringUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;


@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes({List.class})
public class ListTypeHandler implements TypeHandler<List<String>> {

    @Override
    public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        String hobbys = StringUtils.join(parameter, ",");
        try {
            ps.setString(i, hobbys);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String hobbys = cs.getString(columnIndex);
        return Arrays.asList(hobbys.split(","));
    }

    @Override
    public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
        return Arrays.asList(rs.getString(columnIndex).split(","));
    }

    @Override
    public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
        return Arrays.asList(rs.getString(columnName).split(","));
    }
}

   然后,在mybaites配置文件 mybatis-config.xml里面,注册typehandler:

<typeHandlers>
        <typeHandler jdbcType="VARCHAR" javaType="list"
                     handler="com.sankuai.lkl.typeHandler.ListTypeHandler"/>
</typeHandlers>

 最后,在实体类sql mapping xml里面配置,字段的typehandler:

<insert id="insertPerson" parameterType="person">
        INSERT INTO person (id,name,sex,hobbys,data_time) values(#{id},#{name},#{sex},#{hobbys,typeHandler=com.sankuai.lkl.typeHandler.ListTypeHandler},#{date})
</insert>


<resultMap id="personMap" type="person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="hobbys" column="hobbys" typeHandler="com.sankuai.lkl.typeHandler.ListTypeHandler"/>
        <result property="date" column="data_time"/>
</resultMap>

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值