TypeHandler用于JDBC类型与Java类型的转换,例如java.sql.Date与java.util.date的转换,MyBatis默认实现了很多常用的TypeHandler,向数据库中每个列中写入或读出数据时都会先经过TypeHandler的处理。
baseTypeHandlerTypeHandler是MyBatis中处理Java与数据库类型转换的接口,可以通过实现此接口自定义类型处理器,但自定义类型处理器是并不是直接实现TypeHandler接口,而是继承baseTypeHandler抽象类,baseTypeHandler抽象类实现了TypeHandler接口并实现了一部分功能,子类只需实现其中的若干方法:
public abstract class baseTypeHandler示例extends TypeReference implements TypeHandler { public abstract T setNonNullParameter(PreparedStatement ps, int i,T param,jdbcType type) throws SQLException; public abstract T getNullableResult(ResultSet resultSet, String columnLabel) throws SQLException; public abstract T getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException; public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException; }
下面将以枚举体的转换为实例说明baseTypeHandler的用法,数据库中的枚举数据:
`status` enum("A","B","C");
Java中的枚举数据:
public enum Status {
A,B,C
}
类型处理器:
public class StatusTypeHandler extends baseTypeHandler{ public StatusTypeHandler() { super(); } @Override public Status SetNonNullParameter(PreparedStatement ps, int i, Status param,jdbcType type) throws SQLException { if(param == Status.A) { ps.setString(i,"A"); } else if(param == Status.B) { ps.setString(i,"B"); } else if(param == Status.C) { ps.setString(i,"C"); } } @Override public Status getNullableResult(ResqultSet resultSet,String columnLabel) throws SQLException { if(resultSet.getString(columnLabel).equals("A")) {return Status.A;} else if(resultSet.getString(columnLabel).equals("B")) {return Status.B;} else if(resultSet.getString(columnLabel).equals("C")) {return Status.C;} return null; } @Override public Status getNullableResult(ResqultSet resultSet,int columnIndex) throws SQLException { if(resultSet.getString(columnIndex).equals("A")) {return Status.A;} else if(resultSet.getString(columnIndex).equals("B")) {return Status.B;} else if(resultSet.getString(columnIndex).equals("C")) {return Status.C;} return null; } @Override public Status getNullableResult(CallableStatement cs,int columnIndex) throws SQLException { if(cs.getString(columnIndex).equals("A")) {return Status.A;} else if(cs.getString(columnIndex).equals("B")) {return Status.B;} else if(cs.getString(columnIndex).equals("C")) {return Status.C;} return null; } }
自定义类型处理器必须提供空参构造器。
类型处理器的注册application.yml
# MyBatis类型处理器在SpringBoot整合中的注册方法 mybatis: # 指定类型处理器的所在包名 type-handlers-package: com.xxx.typehandlerMyBatis注解开发 注解查询 @Insert
@Insert注解的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Insert.List.class)
public @interface Insert {
String[] value();
String databaseId() default "";
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface List {
Insert[] value();
}
}
@Delete
@Delete注解的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Delete.List.class)
public @interface Delete {
String[] value();
String databaseId() default "";
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface List {
Delete[] value();
}
}
@Update
@Update注解的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Update.List.class)
public @interface Update {
String[] value();
String databaseId() default "";
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface List {
Update[] value();
}
}
@Select
@Select注解的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Select.List.class)
public @interface Select {
String[] value();
String databaseId() default "";
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface List {
Select[] value();
}
}
查询示例
@Mapper
@Repository
public interface UserDao {
@Select("select * from users where id = #{id}")
User selectById(@Param("id") Integer id);
}
动态SQL
注解开发支持动态SQL,其做法是使用标签包裹SQL语句,在标签中使用动态SQL即可:
@Mapper
@Repository
public interface UserDao {
@Insert(
"")
boolean insert(@Param("users") List users);
}
参数处理
使用@Param注解可代替配置文件中的parameterType属性,MyBatis框架将根据此注解自动读取参数类型,并且使用@Param注解可指定参数在SQL语句中的引用名,@Param注解的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Param {
String value();
}
返回处理
@ResultType
@Results
@Results注解用处理较为复杂的返回类型,例如需要为某些属性指定类型处理器的返回类型,另外还可以用来处理属性名与字段名不一致的返回类型,其定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Results {
String id() default "";
Result[] value() default {};
}
如果查询方法的返回类型中的属性名与数据库表中的字段名不一致,@Results注解需要与@Result注解配合使用指定属性与字段的对应关系,@Result的定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Results.class)
public @interface Result {
boolean id() default false;
String column() default "";
String property() default "";
Class> javaType() default void.class;
JdbcType jdbcType() default JdbcType.UNDEFINED;
Class extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
One one() default @One;
Many many() default @Many;
}
@Results使用示例:
@Mapper
@Repository
public interface UserDao {
@Results(id="user",value = {
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(column = "post_id",property = "postId")
})
@Select(...)
User selectById(@Param("id") Integer id);
}
当需要多次使用相同的@Results时,可以使用@ResultMap引用@Results的id即可,@ResultMap定义为:
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ResultMap {
String[] value();
}
使用示例:
@Mapper
@Repository
public interface UserDao {
@Results(id="user",value = {
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(column = "post_id",property = "postId")
})
@Select(...)
User selectById(@Param("id") Integer id);
@ResultMap("user")
@Select(...)
User selectByName(@Param("name" String name));
}



