@TableName 、@TableId、@TableField、MyBatis-Plus 字段类型处理器TypeHandler

一、 @TableName 、@TableId、@TableField

@TableName(value = "sys_Log")  //value作用:value指定数据库中的表名
public class SysLog {}

@TableId(type=IdType.AUTO)     //声明主键自增长
 private Long id;

@TableField(value = "email")     //通过tableField进行字段不一致的映射, 比如数据库字段是email,而实体类对应的是mail
private String mail;              

@TableField(select = false)        //查询时,则不返回该字段的值

@TableField(exist = false)         //设置该字段在数据库表中不存在

@TablieField(value = "create_time",fill = FieldFill.INSERT)   //插入时自动填充
 private LocalDateTime createTime;

@TablieField(value = "update_time",fill = FieldFill.INSERT_UPDATE)    //更新时自动填充
 private LocalDateTime updateTime;

二、MyBatis-Plus 字段类型处理器TypeHandler

【使用背景】

当数据库类型与Java对象属性类型不对应,希望通过注解的方式可以解决插入、更新和查询时的数据类型转换问题。

比如说我们Mysql 中的字段类型 为 BigInt,Java程序中的属性类型为 Date,所以我们在入库的时候就是要将
 Date 类型转化为 Long进行入库,在从数据库中取出来的时候,要从 Long 类型转化为 Date 映射到 JavaBean中

【这里插入一个映射表格】

MySQL数据类型 Java实体类属性类型 说明
int Integer 不管是signed还是unsigned,Java实体类型都是Integer
bigint Long 不管是bigint(xxx)括号多少位,不管signed还是unsigned,Java实体类型都是Long
bit byte[] -
tinyint Byte 不管是signed还是unsigned,Java实体类型都是Byte,在java.lang包下
smallint Short 不管是signed还是unsigned,Java实体类型都是Short
char String 不管char是gbk、utf8、utf8mb4等编码类型,Java实体类型都是String
varchar String 不管char是gbk、utf8、utf8mb4等编码类型,Java实体类型都是String
longvarchar String 不管char是gbk、utf8、utf8mb4等编码类型,Java实体类型都是String
date Date java.util.Date
datetime Date java.util.Date
timestamp Date java.util.Date
time Date java.util.Date
float Float 不管是signed还是unsigned,Java实体类型都是Float
decimal Long -
numeric Long -
double Double 不管是signed还是unsigned,Java实体类型都是Double
tinytext String -
text String -
year Date java.util.Date
enum String -

【原理】

MyBatis-Plus 字段类型处理器 TypeHandler,这个 TypeHandler 处于的位置,就是应用程序和数据库之间的拦截器,所有的操作,都会走一遍这里。@TableField是mybatis-plus的一种字段处理器,该处理器可以解决字段类型转换的问题,但是需要typeHandler Class 类型处理器进行转换。

数据库类型与Java对象属性类型不对应,通过TypeHandler注解的方式,
setParameter方法可以解决插入、更新时的数据转换问题,
getResult方法查询时的数据类型转换问题。这里可以实现TypeHandler类型来实现自定义类型处理器。

【TypeHandler源码;可参照BaseTypeHandler 、BigIntegerTypeHandler 根据自己需要自定义处理类实现TypeHandler】

 public interface TypeHandler {
 
   /**
     * 入库前的类型转换;用于把 java 对象设置到 PreparedStatement 的参数中
    */
   void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
 
   /**
     * 得到结果。
     * 查询后的数据处理; 用于从 ResultSet 中根据列名取出数据转换为 java 对象
    */
   T getResult(ResultSet rs, String columnName) throws SQLException;
  
    // 用于从 ResultSet 中根据索引位置取出数据转换为 java 对象
   T getResult(ResultSet rs, int columnIndex) throws SQLException;
     
   // 用于从 CallableStatement 中根据存储过程取出数据转换为 java 对象
   T getResult(CallableStatement cs, int columnIndex) throws SQLException;
 
 }

【BaseTypeHandler 实现 TypeHandler 】

 public abstract class BaseTypeHandler extends TypeReference implements TypeHandler {
 
   @Override
   public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
     if (parameter == null) {
       if (jdbcType == null) {
         throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
       }
       try {
         ps.setNull(i, jdbcType.TYPE_CODE);
       } catch (SQLException e) {
         throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
               + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
               + "Cause: " + e, e);
       }
     } else {
       try {
       // 设置不为null的参数,进行入库 ,此处是抽象类,下层还有实现类,
         setNonNullParameter(ps, i, parameter, jdbcType);
       } catch (Exception e) {
         throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "
               + "Try setting a different JdbcType for this parameter or a different configuration property. "
               + "Cause: " + e, e);
       }
     }
   }
 
   @Override
   public T getResult(ResultSet rs, String columnName) throws SQLException {
     try {
       //  这里从数据库中获取到数据,然后进行类型的一个设置
       return getNullableResult(rs, columnName);
     } catch (Exception e) {
       throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + e, e);
     }
   }
 
   @Override
   public T getResult(ResultSet rs, int columnIndex) throws SQLException {
     try {
       return getNullableResult(rs, columnIndex);
     } catch (Exception e) {
       throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set.  Cause: " + e, e);
     }
   }
 
   @Override
   public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
     try {
       return getNullableResult(cs, columnIndex);
     } catch (Exception e) {
       throw new ResultMapException("Error attempting to get column #" + columnIndex + " from callable statement.  Cause: " + e, e);
     }
   }
 
     // 这里就是设置为 不为 null 时的入库
   public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
 
   /**
    * 获取可为空的结果。
    */
   public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
 
   public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
 
   public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
 
 }
 

【BigIntegerTypeHandler 继承 BaseTypeHandler 】

用于 java 类型 BigDecimal,jdbc 类型 REAL、DECIMAL、NUMERIC
public class BigIntegerTypeHandler extends BaseTypeHandler {
 
   @Override
   public void setNonNullParameter(PreparedStatement ps, int i, BigInteger parameter, JdbcType jdbcType) throws SQLException {
     // 这里是转为 BigDecimal ,所以这里就算 setBigDecimal,
     // 那么我们就可以猜测,它还支持其他的方法,Date的话,那就是setDate
     ps.setBigDecimal(i, new BigDecimal(parameter));
   }
 
   @Override
   public BigInteger getNullableResult(ResultSet rs, String columnName) throws SQLException {
     BigDecimal bigDecimal = rs.getBigDecimal(columnName);
       // 这里是rs.getBigDecimal ,我们待会去试一下能否getDate就可以了
     return bigDecimal == null ? null : bigDecimal.toBigInteger();
   }
 
    // 这两个暂时没有做了解,Debug的时候,断点没有执行到这,后期再补一块的知识
    // 但是为了以防万一,我们待会也会照着它的方式将代码改成这样
   @Override
   public BigInteger getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
     BigDecimal bigDecimal = rs.getBigDecimal(columnIndex);
     return bigDecimal == null ? null : bigDecimal.toBigInteger();
   }
 
   @Override
   public BigInteger getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
     BigDecimal bigDecimal = cs.getBigDecimal(columnIndex);
     return bigDecimal == null ? null : bigDecimal.toBigInteger();
   }
 }
 

【实践】

实际开发中,我们可以继承 org.apache.ibatis.type.BaseTypeHandler 类型来实现自定义类型处理器。这个类型是抽象类型,实现了 TypeHandler 的方法进行通用流程的封装,做了异常处理,并定义了几个类似的抽象方法,如下所示。
继承 BaseTypeHandler 类型可以极大地降低开发难度。

·

比如】User 中有个属性的类型是 List 类型,对应的保存到数据库中的字段为VARCHAR 类型。要通过 TypeHandler 在插入的时候把List类型数据转换为String 类型处理,在查询的时候要把查询得到的字符串转换为 List 类型。

1、继承BaseTypeHandler实现自定义TypeHandler


public class ListTypeHandler extends BaseTypeHandler> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, String.join(",", parameter));
    }

    @Override
    public List getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String s = rs.getString(columnName);
        return s == null ? null : Arrays.asList(s.split(","));
    }

    @Override
    public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String s = rs.getString(columnIndex);
        return s == null ? null : Arrays.asList(s.split(","));
    }

    @Override
    public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String s = cs.getString(columnIndex);
        return s == null ? null : Arrays.asList(s.split(","));
    }
}


2、指定字段上注解

@TableField(typeHandler = ListTypeHandler .class)

AbstractJsonTypeHandler

mybatisplus已经提供了FastJson、Gson和JackSon的json转java对象的AbstractJsonTypeHandler的实现类;

//json从数据库中取出转换成对象

@TableField(typeHandler = FastjsonTypeHandler.class)
private 实体类 xxx;

补充

在实体类上使用映射注解:
@TableName(value = “a”, autoResultMap = true)
autoResultMap参数为true时,表明个别字段在查询处理的时候自动转换为对象,只适合设置了TypeHandler、jdbcTyped的情况。autoResultMap 自动映射,通常配合 @TableField() 一起使用,确定映射规范性。

你可能感兴趣的:(MyBatis-Plus,mybatis,数据库,java)