Mybatis - 自定義BaseMapper SQLProvider篇

weixin_33785972發表於2017-05-21

SQL Provider

  • @InsertProvider
  • @UpdateProvider
  • @DeleteProvider
  • @SelectProvider

這些可選的SQL註解允許你指定一個類名和一個方法,在執行時來返回動態的SQL。

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);

class UserSqlBuilder {
    public String buildGetUsersByName(final String name) {
        return new SQL(){{
            SELECT("*");
            FROM("users");
            if (name != null) {
                WHERE("name like #{value} || '%'");
            }
            ORDER_BY("id");
        }}.toString();
    }
}

BaseMapper

我們可以使用 SQLProvider 構建屬於自己的BaseMapper。

public interface BaseMapper<T, K> {
    @InsertProvider(type = SqlSourceBuilder.class, method = "build")
    public Long insert(T model);

    @UpdateProvider(type = SqlSourceBuilder.class, method = "build")
    public Long updateById(T model);

    @DeleteProvider(type = SqlSourceBuilder.class, method = "build")
    public Long deleteById(@Param("id") K id);

    @SelectProvider(type = SqlSourceBuilder.class, method = "build")
    public T getById(@Param("id") K id);

    @SelectProvider(type = SqlSourceBuilder.class, method = "build")
    public Boolean existById(@Param("id") K id);
}

SqlSourceBuilder

把用SQLProvider生成的ProviderSqlSource替換成DynamicSqlSource

public class SqlSourceBuilder {
    public static String build(Configuration configuration) {
        for (MappedStatement mappedStatement : configuration.getMappedStatements()) {
            if (mappedStatement.getSqlSource() instanceof ProviderSqlSource) {
                Class<?> providerClass = getProviderClass(mappedStatement);
                if (providerClass != SqlSourceBuilder.class)
                    continue;

                Class<?> mapperClass = getMapperClass(mappedStatement);
                Class<?>[] generics = getMapperGenerics(mapperClass);
                Class<?> modelClass = generics[0];
                Class<?> primaryFieldClass = generics[1];
                ResultMap resultMap = getResultMap(mappedStatement, modelClass);

                String sqlScript = getSqlScript(mappedStatement, mapperClass, modelClass, primaryFieldClass, resultMap);
                SqlSource sqlSource = createSqlSource(mappedStatement, sqlScript);
                setSqlSource(mappedStatement, sqlSource);
            }
        }
        return "sql";
    }
    ...
}

MapperTest 測試

public class MapperTest {
    @Test
    public void test() throws Exception {
        SqlSessionFactory sessionFactory = MybatisConfig.getSessionFactory();
        SqlSession session = sessionFactory.openSession();

        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = null;

        // 新增測試
        System.out.println("------------ 新增測試 ------------");
        user = new User();
        user.setId(1L);
        user.setAccount("conanli");
        user.setPassword("123456");
        System.out.println("insert: " + userMapper.insert(user));

        // 更新測試
        System.out.println("------------ 更新測試 ------------");
        user = new User();
        user.setId(1L);
        user.setPassword("111111");
        System.out.println("update: " + userMapper.updateById(user));

        // 獲取測試
        System.out.println("------------ 獲取測試 ------------");
        System.out.println("user: " + userMapper.getById(1L));

        // 刪除測試
        System.out.println("------------ 刪除測試 ------------");
        System.out.println("delete: " + userMapper.deleteById(1L));

        // 存在測試
        System.out.println("------------ 存在測試 ------------");
        System.out.println("exist: " + userMapper.existById(1L));

        session.commit();
        session.close();
    }
}

完整示例:GitHub
PS:本文使用的是mybatis-3.4.4

相關文章