MyBatis项目笔记

5 篇文章 0 订阅
4 篇文章 0 订阅

TypeHandler

  TypeHandler用于JDBC类型与Java类型的转换,例如java.sql.Datejava.util.date的转换,MyBatis默认实现了很多常用的TypeHandler,向数据库中每个列中写入或读出数据时都会先经过TypeHandler的处理。

BaseTypeHandler

  TypeHandlerMyBatis中处理Java与数据库类型转换的接口,可以通过实现此接口自定义类型处理器,但自定义类型处理器是并不是直接实现TypeHandler接口,而是继承BaseTypeHandler抽象类,BaseTypeHandler抽象类实现了TypeHandler接口并实现了一部分功能,子类只需实现其中的若干方法:

public abstract class BaseTypeHandler<T> 
    extends TypeReference<T> implements TypeHandler<T> {
    /* 作用说明:用于将Java类型转换为数据库类型
       参数说明:
       1.参数1,用于获取当前编译过的SQL语句,使用此对象可直接向数据库中写入数据
       2.参数2,用于获取当前SQL语句中占位符的索引,通过ps.setXXX(i,obj)可向数据库写入数据
       3.参数3,用于获取当前传入的参数
       4.参数4,用于获取当前参数的数据库类型 */
    public abstract T setNonNullParameter(PreparedStatement ps,
                                          int i,T param,jdbcType type) throws SQLException;
    /* 作用说明:用于将数据库类型转换为Java类型
       参数说明:
       1.参数1,用于获取查询结果集
       2.参数2,用于获取当前列名,可以通过resultSet.getXXX(columnLabel)获取对应的字段值 */
    public abstract T getNullableResult(ResultSet resultSet,
                                        String columnLabel) throws SQLException;
    /* 作用说明:用于将数据库类型转换为Java类型
       参数说明:
       1.参数1,用于获取查询结果集
       2.参数2,用于获取当前列索引,可以通过resultSet.getXXX(columnIndex)获取对应的字段值 */
    public abstract T getNullableResult(ResultSet resultSet,
                                        int columnIndex) throws SQLException;
    /* 作用说明:用于将数据库类型转换为Java类型
       参数说明:
       1.参数1,用于获取查询结果集
       2.参数2,用于获取当前列索引,可以通过cs.getXXX(columnIndex)获取对应的字段值 */
    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<Status> {
    
    /* 注意必须提供空参构造器 */
    public StatusTypeHandler() {
        super();
    }
    
    @Override
    public Status SetNonNullParameter(PreparedStatement ps,
                                      int i,
                                      Status param,jdbcType type) throws SQLException {
        /* 将Java类型转换为数据库类型 */
        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 {
        /* 将数据库类型转换为Java类型 */
        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.typehandler

MyBatis注解开发

注解查询

@Insert

  @Insert注解的定义为:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Insert.List.class)
public @interface Insert {
    
    /* 指定insert SQL语句 */
    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 {
    
    /* 指定delete SQL语句 */
    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 {
    
    /* 指定update SQL语句 */
    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 {
    
    /* 指定select SQL语句 */
    String[] value();
    /* 指定数据库版本号,用于区分不同的数据库 */
    String databaseId() default "";
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface List {
        Select[] value();
    }
}

查询示例

/* SpringBoot整合下的注解 */
@Mapper
@Repository
public interface UserDao {
    @Select("select * from users where id = #{id}")
    User selectById(@Param("id") Integer id);
}

动态SQL

  注解开发支持动态SQL,其做法是使用<script></script>标签包裹SQL语句,在标签中使用动态SQL即可:

/* SpringBoot整合下的注解 */
@Mapper
@Repository
public interface UserDao {
    
    /* 注意""使用\"\"转义 */
    @Insert(
        "<script>" +
        "insert into users(name,password,gender,age) " + 
        "values" + 
        "<foreach collection=\"users\" item=\"user\" separator=\",\">" + 
        "(user.name,user.password,user.gender,user.age)" +
        "</foreach>" +
        "</script>")
    boolean insert(@Param("users") List<User> 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 {
    /* 为结果集指定id,方便@ResultMap引用 */
    String id() default "";
    /* @Result注解数组 */
    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 "";
    /* Java实体类属性名 */
    String property() default "";
    /* Java实体类属性类型 */
    Class<?> javaType() default void.class;
    /* JDBC类型 */
    JdbcType jdbcType() default JdbcType.UNDEFINED;
    /* 类型处理器 */
    Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
    /* 一对一关联查询 */
    One one() default @One;
    /* 一对多关联查询 */
    Many many() default @Many;
}

  @Results使用示例:

/* SpringBoot整合下的注解 */
@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引用@Resultsid即可,@ResultMap定义为:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ResultMap {
    /* 引用@Results的id */
    String[] value();
}

  使用示例:

/* SpringBoot整合下的注解 */
@Mapper
@Repository
public interface UserDao {
    /* id指定唯一标识,value指定@Result数组 */
    @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引用@Results的id;
       @ResultMap注解仅有value一个属性 */
    @ResultMap("user")
    @Select(...)
    User selectByName(@Param("name" String name));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值