SpringBoot基于tk.mybatis的通用API操作(基于反射的通用模糊查询)

一.背景

在项目很多基本的操作时,编码费时费力,所以想简化基本的增删改查,让开发更加高效,这个插件里面封装好了我们需要用到的很多sql语句,不过这个插件是通过我们去调用它封装的各种方法来实现sql语句的效果。对于单表查询不需要写SQL语句,这样就不用像mybatis那样每次写一个接口就要写一条sql语句。这样大大减少了我们的工作量。只需要写特殊的sql

二.搭建与使用

  1. tk.mybatis的maven依赖包


    tk.mybatis
    mapper-spring-boot-starter
    1.1.1


    tk.mybatis
    mapper
    3.4.0


    org.mybatis
    mybatis
    3.4.2


    com.google.guava
    guava
    27.0.1-jre

2.添加一个UserInfo实体类

SpringBoot基于tk.mybatis的通用API操作(基于反射的通用模糊查询)_第1张图片

3.通用业务层实现,编写项目ServiceImple时需要继承该BaseService,以及其本身自己定义的IService实现基本的增删改查

public abstract class BaseService implements IBaseService {

    /**
     * The Logger.
     */
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * The Mapper.
     */
    @Autowired
    protected Mapper mapper;

    /**
     * Gets mapper.
     *
     * @return the mapper
     */
    public Mapper getMapper() {
        return mapper;
    }

    /**
     * Select list.
     *
     * @param record the record
     * @return the list
     */
    @Override
    public List select(T record) {
        return mapper.select(record);
    }

    /**
     * Select by key t.
     *
     * @param key the key
     * @return the t
     */
    @Override
    public T selectByKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    /**
     * Select all list.
     *
     * @return the list
     */
    @Override
    public List selectAll() {
        return mapper.selectAll();
    }

    /**
     * Select one t.
     *
     * @param record the record
     * @return the t
     */
    @Override
    public T selectOne(T record) {
        return mapper.selectOne(record);
    }

    /**
     * Select count int.
     *
     * @param record the record
     * @return the int
     */
    @Override
    public int selectCount(T record) {
        return mapper.selectCount(record);
    }

    /**
     * Select by example list.
     *
     * @param example the example
     * @return the list
     */
    @Override
    public List selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    /**
     * Save int.
     *
     * @param record the record
     * @return the int
     */
    @Override
    public int save(T record) {
        return mapper.insertSelective(record);
    }

    /**
     * Batch save int.
     *
     * @param list the list
     * @return the int
     */
    @Override
    public int batchSave(List list) {
        int result = 0;
        for (T record : list) {
            int count = mapper.insertSelective(record);
            result += count;
        }
        return result;
    }

    /**
     * Update int.
     *
     * @param entity the entity
     * @return the int
     */
    @Override
    public int update(T entity) {
        return mapper.updateByPrimaryKeySelective(entity);
    }

    /**
     * Delete int.
     *
     * @param record the record
     * @return the int
     */
    @Override
    public int delete(T record) {
        return mapper.delete(record);
    }

    /**
     * Delete by key int.
     *
     * @param key the key
     * @return the int
     */
    @Override
    public int deleteByKey(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    /**
     * Batch delete int.
     *
     * @param list the list
     * @return the int
     */
    @Override
    public int batchDelete(List list) {
        int result = 0;
        for (T record : list) {
            int count = mapper.delete(record);
            if (count < 1) {
                logger.error("删除数据失败");
                throw new SystemException("990108");
            }
            result += count;
        }
        return result;
    }

    /**
     * Select count by example int.
     *
     * @param example the example
     * @return the int
     */
    @Override
    public int selectCountByExample(Object example) {
        return mapper.selectCountByExample(example);
    }

    /**
     * Update by example int.
     *
     * @param record  the record
     * @param example the example
     * @return the int
     */
    @Override
    public int updateByExample(T record, Object example) {
        return mapper.updateByExampleSelective(record, example);
    }

    /**
     * Delete by example int.
     *
     * @param example the example
     * @return the int
     */
    @Override
    public int deleteByExample(Object example) {
        return mapper.deleteByPrimaryKey(example);
    }

    /**
     * Select by row bounds list.
     *
     * @param record    the record
     * @param rowBounds the row bounds
     * @return the list
     */
    @Override
    public List selectByRowBounds(T record, RowBounds rowBounds) {
        return mapper.selectByRowBounds(record, rowBounds);
    }

    /**
     * Select by example and row bounds list.
     *
     * @param example   the example
     * @param rowBounds the row bounds
     * @return the list
     */
    @Override
    public List selectByExampleAndRowBounds(Object example, RowBounds rowBounds) {
        return mapper.selectByExampleAndRowBounds(example, rowBounds);
    }
}

 

4.通用接口(编写项目Iservice时需要继承该IBaseService实现基本的增删改查)

public interface IBaseService {
    /**
     * 根据实体中的属性值进行查询, 查询条件使用等号  @param record the record
     *
     * @param record the record
     * @return the list
     */
    List select(T record);

    /**
     * 根据主键字段进行查询, 方法参数必须包含完整的主键属性, 查询条件使用等号  @param key the key
     *
     * @param key the key
     * @return the t
     */
    T selectByKey(Object key);

    /**
     * 查询全部结果, select(null)方法能达到同样的效果  @return the list
     *
     * @return the list
     */
    List selectAll();

    /**
     * 根据实体中的属性进行查询, 只能有一个返回值, 有多个结果是抛出异常, 查询条件使用等号  @param record the record
     *
     * @param record the record
     * @return the t
     */
    T selectOne(T record);

    /**
     * 根据实体中的属性查询总数, 查询条件使用等号  @param record the record
     *
     * @param record the record
     * @return the int
     */
    int selectCount(T record);

    /**
     * 保存一个实体, null的属性不会保存, 会使用数据库默认值  @param record the record
     *
     * @param record the record
     * @return the int
     */
    int save(T record);

    /**
     * 批量保存  @param list the list
     *
     * @param list the list
     * @return the int
     */
    @Transactional(rollbackFor = Exception.class)
    int batchSave(List list);

    /**
     * 根据主键更新属性不为null的值  @param entity the entity
     *
     * @param entity the entity
     * @return the int
     */
    int update(T entity);

    /**
     * 根据实体属性作为条件进行删除, 查询条件使用等号  @param record the record
     *
     * @param record the record
     * @return the int
     */
    int delete(T record);

    /**
     * 批量删除  @param list the list
     *
     * @param list the list
     * @return the int
     */
    @Transactional(rollbackFor = Exception.class)
    int batchDelete(List list);

    /**
     * 根据主键字段进行删除, 方法参数必须包含完整的主键属性  @param key the key
     *
     * @param key the key
     * @return the int
     */
    int deleteByKey(Object key);

    /**
     * 这个查询支持通过Example类指定查询列, 通过selectProperties方法指定查询列  @param example the example
     *
     * @param example the example
     * @return the list
     */
    List selectByExample(Object example);

    /**
     * 根据Example条件进行查询总数  @param example the example
     *
     * @param example the example
     * @return the int
     */
    int selectCountByExample(Object example);

    /**
     * 根据Example条件更新实体record包含的不是null的属性值  @param record the record
     *
     * @param record  the record
     * @param example the example
     * @return the int
     */
    int updateByExample(@Param("record") T record, @Param("example") Object example);

    /**
     * 根据Example条件删除数据  @param example the example
     *
     * @param example the example
     * @return the int
     */
    int deleteByExample(Object example);
    
    /**
     * 根据实体属性和RowBounds进行分页查询  @param record the record
     *
     * @param record    the record
     * @param rowBounds the row bounds
     * @return the list
     */
    List selectByRowBounds(T record, RowBounds rowBounds);

    /**
     * 根据example条件和RowBounds进行分页查询  @param example the example
     *
     * @param example   the example
     * @param rowBounds the row bounds
     * @return the list
     */
    List selectByExampleAndRowBounds(Object example, RowBounds rowBounds);

}

 

 

5.最基本的Mapper ,编写项目Mapper时继承该Mapper实现基本的增删改查

public interface BaseMapper extends Mapper, MySqlMapper {
}

 

6.使用方式

SpringBoot基于tk.mybatis的通用API操作(基于反射的通用模糊查询)_第2张图片

这样就实现了基本功能API,基本的增删改查都可以使用啦

附:基于反射的通用模糊查询

/**
 * 通用模糊查询
 * 只支持本身类型属性模糊查询,字典label目前不支持
 *
 * @param keyValue     模糊查询的值
 * @param examplClass  实体对象的字节码对象
 * @param propertyList 需查询的属性(没有就默认查询全部)
 * @return List 查询结果
 * @author 
 * @date 
 */
@Override
public List keyValueByExample(String keyValue, Class examplClass, List propertyList) {
    if (examplClass == null) {
        throw new RuntimeException("Class can't be null");
    }
    if (StringUtils.isBlank(keyValue)) {
        throw new RuntimeException("keyValue property to search can't be null");
    }
    keyValue = "%" + keyValue + "%";
    boolean needCheckPropertyList = (propertyList != null && propertyList.size() > 0);
    // create Example Criteria
    Example example = new Example(examplClass);
    Example.Criteria criteria;
    // get Class Field
    List fields = getFieldList(examplClass);
    for (Field field : fields) {
        field.setAccessible(true);
        // Field tyep: int / java.lang.String / java.lang.Integer / java.lang.Doubbo / java.math.BigDecimal
        // int[][] /int / float /doubbo
        String canonicalNameType = field.getType().getCanonicalName();
        // wether array  Enum Synthetic continue
        if (field.isEnumConstant() || field.isSynthetic() || canonicalNameType.contains("[]")) {
            continue;
        }
        //Field Name
        String fieldName = field.getName();
        // judge current filed wether in propertyList need to be  select like
        criteria = example.createCriteria();
        if (needCheckPropertyList) {
            for (String property : propertyList) {
                if (property.equals(fieldName)) {
                    if ("java.lang.String".equals(canonicalNameType)) {
                        criteria.andLike(property, keyValue);
                        example.or(criteria);
                    }
                    // TODO 其它类型
                }
            }
        } else {
            if ("java.lang.String".equals(canonicalNameType)) {
                criteria.andLike(fieldName, keyValue);
                example.or(criteria);
            }
            // TODO 其它类型
        }
    }
    return mapper.selectByExample(example);
}

/**
 * 获取当前字节码对象的属性包含父类属性
 *
 * @param clazz 字节码对象
 * @return 属性集合
 * @author 
 * @date 
 */
public static List getFieldList(Class clazz) {
    if (null == clazz) {
        return null;
    }
    List fieldList = new LinkedList<>();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        /** 过滤静态属性**/
        if (Modifier.isStatic(field.getModifiers())) {
            continue;
        }
        /** 过滤transient 关键字修饰的属性**/
        if (Modifier.isTransient(field.getModifiers())) {
            continue;
        }
        fieldList.add(field);
    }
    /** 处理父类字段**/
    Class superClass = clazz.getSuperclass();
    if (superClass.equals(Object.class)) {
        return fieldList;
    }
    List fieldListSupper = getFieldList(superClass);
    if (fieldListSupper != null) {
        fieldList.addAll(fieldListSupper);
    }
    return fieldList;
}

 使用如下

@Test
public void keyValueByExample() {
    List daList = userService.keyValueByExample("da", User.class, null);
    System.out.println("<< ==== keyValueByExample ===== >> " + daList);
}

你可能感兴趣的:(javaEE)