动态SQL构建(@SelectProvider @InsertProvider @UpdateProvider @DeleteProvider )

Exisi 2021-03-27 07:46:51
Categories: Tags:
  • 动态 SQL 构建注解用于指定一个类或方法,该类或方法返回一个字符串类型的SQL语句,用于查询插入更新和删除操作

注解

说明

@SelectProvider

用于构建动态查询SQL

@InsertProvider

用于构建动态新增SQL

@UpdateProvider

用于构建动态更新SQL

@DeleteProvider

用于构建动态删除SQL

 

  • 动态 SQL 构建注解都有以下属性:

参数

描述

type

用于指定类名 (type 属性是 value 的别名)

value

用于指定类名

method

指定工具类的方法,必须是 public 的,返回值必须为 String,可以为 static

databaseId

MyBatis 3.5.5以上可用, 如果有一个配置好的 DatabaseIdProvider, MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时存在带 databaseId 和不带 databaseId 属性的相同语句,则后者会被舍弃。

示例

  • UserMapper.java

public interface UserMapper(){

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUserByIdSql")

UserInfo getUserById(Integer userId);

 

@InsertProvider(type=UserSqlBuilder.class, method = "buildInsertUserSql")

Integer updateUser(UserInfo user);

 

@UpdateProvider(type = UserSqlBuilder.class, method = "buildUpdateUserSql")

public int updateUser(UserInfo user);

 

@DeleteProvider(type = UserSqlBuilder.class, method = "buildDeleteUserSql")

public int deleteUser(Integer userId);

}

 

  • UserSqlBuilder.java

public class UserSqlBuilder {

 

public String buildGetUserByIdSql(@Param("userId") Integer userId) {

return new SQL() {

  {

                    SELECT("*");

                    FROM("tb_user");

                    WHERE("user_id = #{userId}");

  }

}.toString();

}

 

public String buildInsertUserSql(UserInfo user) {

return new SQL() {

  {

                    INSERT_INTO("tb_user");

                    VALUES("user_name", "#{userName}");

                    VALUES("blog_url", "#{blogUrl}");

                    VALUES("blog_remark", "#{blogRemark}");

  }

}.toString();

        }

 

        public String buildUpdateUserSql(UserInfo user) {

return new SQL()  {

  {

                    UPDATE("tb_user");

                    SET("user_name = #{userName} ,blog_url=#{blogUrl} ,blog_remark=#{blogRemark}");

                    WHERE("user_id = #{userId}");

  }

}.toString();

}

 

        public String buildDeleteUserSql(@Param("userId") Integer userId) {

return new SQL() {

  {

                    DELETE_FROM("tb_user");

                    WHERE("user_id = #{userId}");

  }

}.toString();

}

}

 

  • 多个参数的动态 SQL 构建注解

示例

  • UserMapper.java

public interface UserMapper(){

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")

List<User> getUsersByName(@Param("name") String name, @Param("orderByColumn") String orderByColumn);

}

 

  • UserSqlBuilder.java

public class UserSqlBuilder {

 

// 如果不使用 @Param,就应该定义与 mapper 方法相同的参数

public static String buildGetUsersByName(

final String name, final String orderByColumn) {

return new SQL() {

  {

SELECT("*");

FROM("users");

WHERE("name like #{name} || '%'");

ORDER_BY(orderByColumn);

  }

}.toString();

}

 

// 如果使用 @Param,就可以只定义需要使用的参数

public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {

return new SQL() {

  {

SELECT("*");

FROM("users");

WHERE("name like #{name} || '%'");

ORDER_BY(orderByColumn);

  }

}.toString();

}

}

  • type value 属性,必须指定任意一个

 

  • MyBatis 3.5.1 后的版本中,提供了 ProviderMethodResolver 接口,只需要实现这个接口,就会将映射器方法的调用解析到实现的同名方法上,而无需使用  method 属性指定方法

示例

  • UserSqlProvider.java

// 在你的 provider 类中实现 ProviderMethodResolver 接口

public class UserSqlProvider implements ProviderMethodResolver {

// 默认实现中,会将映射器方法的调用解析到实现的同名方法上

public static String getUsersByName(final String name) {

return new SQL() {

  {

SELECT("*");

FROM("users");

if (name != null) {

WHERE("name like #{value} || '%'");

}

ORDER_BY("id");

  }

}.toString();

}

}

 

  • UserMapper.java

public interface UserMapper() {

@SelectProvider(UserSqlProvider.class)

List<User> getUsersByName(String name);

}

 

  • 但是 MyBatis 3.5.1 后的版本中,如果在全局配置中指定了 defaultSqlProviderType,两个属性都可以忽略,如果省略,MyBatis 将使用 defaultSqlProviderType 所指定的类

示例

  • UserTest.java

Configuration configuration = new Configuration();

// 让所有映射方法在同一个 sql provider 类里面

configuration.setDefaultSqlProviderType(TemplateFilePathProvider.class);

 

  • UserMapper.java

public interface UserMapper {

 

@SelectProvider // 等价于 @SelectProvider(TemplateFilePathProvider.class)

User findUser(int id);

 

@InsertProvider // 等价于 @InsertProvider(TemplateFilePathProvider.class)

void createUser(User user);

 

@UpdateProvider // 等价于 @UpdateProvider(TemplateFilePathProvider.class)

void updateUser(User user);

 

@DeleteProvider // 等价于 @DeleteProvider(TemplateFilePathProvider.class)

void deleteUser(int id);

}

 

  • 从版本 3.5.1 开始,可以省略 method 属性,MyBatis 将会使用 ProviderMethodResolver 接口解析方法的具体实现。如果解析失败,MyBatis 将会使用名为 provideSql 的降级实现

 

 

来自 <https://mybatis.org/mybatis-3/zh/java-api.html#sqlSessions>