Skip to content

Commit

Permalink
扩展一些根据属性及条件值查询的通用方法
Browse files Browse the repository at this point in the history
  • Loading branch information
DiligentNezha authored and abel533 committed Oct 21, 2019
1 parent 1764748 commit bd10103
Show file tree
Hide file tree
Showing 8 changed files with 583 additions and 0 deletions.
11 changes: 11 additions & 0 deletions extra/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
<name>mapper-extra</name>
<description>Mybatis 通用 Mapper 扩展方法</description>

<properties>
<jdk.version>1.8</jdk.version>
<mapper-module.version>1.1.5</mapper-module.version>
</properties>

<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
Expand All @@ -47,6 +52,12 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-weekend</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-base</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package tk.mybatis.mapper.additional.select;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.weekend.Fn;

import java.util.List;

/**
* 根据属性查询接口
*
* @param <T> 不能为空
*
* @author jingkaihui
* @date 2019/10/11
*/
@RegisterMapper
public interface SelectByPropertyMapper<T> {

/**
* 根据属性及对应值进行查询,只能有一个返回值,有多个结果时抛出异常,查询条件使用等号
*
* @param fn 查询属性
* @param value 属性值
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
T selectOneByProperty(@Param("fn") Fn<T, ?> fn, @Param("value") Object value);

/**
* 根据属性及对应值进行查询,有多个返回值,查询条件使用等号
*
* @param fn 查询属性
* @param value 属性值
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
List<T> selectByProperty(@Param("fn") Fn<T, ?> fn, @Param("value") Object value);

/**
* 根据属性及对应值进行查询,查询条件使用 in
*
* @param fn 查询属性
* @param values 属性值集合,集合不能空
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
List<T> selectInByProperty(@Param("fn") Fn<T, ?> fn, @Param("values") List<?> values);

/**
* 根据属性及对应值进行查询,查询条件使用 between
*
* @param fn 查询属性
* @param begin 开始值
* @param end 开始值
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
List<T> selectBetweenByProperty(@Param("fn") Fn<T, ?> fn, @Param("begin") Object begin, @Param("end") Object end);

/**
* 根据属性及对应值进行查询,检查是否存在对应记录,查询条件使用等号
*
* @param fn 查询属性
* @param value 属性值
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
boolean existsWithProperty(@Param("fn") Fn<T, ?> fn, @Param("value") Object value);

/**
* 根据属性及对应值进行查询,统计符合条件的记录数,查询条件使用等号
*
* @param fn 查询属性
* @param value 属性值
* @return
*/
@SelectProvider(type = SelectPropertyProvider.class, method = "dynamicSQL")
int selectCountByProperty(@Param("fn") Fn<T, ?> fn, @Param("value") Object value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
package tk.mybatis.mapper.additional.select;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.entity.EntityTable;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import tk.mybatis.mapper.util.StringUtil;

import java.util.Objects;

/**
* @author jingkaihui
* @date 2019/10/11
*/
public class SelectPropertyProvider extends MapperTemplate {

private static final Log log = LogFactory.getLog(SelectPropertyProvider.class);

public SelectPropertyProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}

/**Ba
* 根据属性查询,只能有一个返回值,有多个结果时抛出异常,查询条件使用等号
*
* @param ms
* @return
*/
public String selectOneByProperty(MappedStatement ms) {
String propertyHelper = SelectPropertyProvider.class.getName();
Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
sql.append("<if test=\"@");
sql.append(propertyHelper);
sql.append("@existsWhereCondition(value, ");
sql.append(isNotEmpty());
sql.append(")");
sql.append("\">\n");
String entityClassName = entityClass.getName();
//通过实体类名获取运行时属性对应的字段
String ognl = new StringBuilder("${@")
.append(propertyHelper)
.append("@getColumnByProperty(@java.lang.Class@forName(\"")
.append(entityClassName)
.append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString();
sql.append(ognl + " = #{value}\n");
sql.append("</if>\n");
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据属性查询,查询条件使用等号
*
* @param ms
* @return
*/
public String selectByProperty(MappedStatement ms) {
String propertyHelper = SelectPropertyProvider.class.getName();
Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
sql.append("<if test=\"@");
sql.append(propertyHelper);
sql.append("@existsWhereCondition(value, ");
sql.append(isNotEmpty());
sql.append(")");
sql.append("\">\n");
String entityClassName = entityClass.getName();
//通过实体类名获取运行时属性对应的字段
String ognl = new StringBuilder("${@")
.append(propertyHelper)
.append("@getColumnByProperty(@java.lang.Class@forName(\"")
.append(entityClassName)
.append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString();
sql.append(ognl + " = #{value}\n");
sql.append("</if>\n");
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据属性查询,查询条件使用 in
*
* @param ms
* @return
*/
public String selectInByProperty(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
String entityClassName = entityClass.getName();
String propertyHelper = SelectPropertyProvider.class.getName();
String sqlSegment =
"${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\"),"
+ "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} in"
+ "<foreach open=\"(\" close=\")\" separator=\",\" collection=\"values\" item=\"obj\">\n"
+ "#{obj}\n"
+ "</foreach>\n";
sql.append(sqlSegment);
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据属性查询,查询条件使用 between
*
* @param ms
* @return
*/
public String selectBetweenByProperty(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
String entityClassName = entityClass.getName();
String propertyHelper = SelectPropertyProvider.class.getName();
String sqlSegment =
"${@" + propertyHelper + "@getColumnByProperty(@java.lang.Class@forName(\"" + entityClassName + "\"),"
+ "@tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))} "
+ "between #{begin} and #{end}";
sql.append(sqlSegment);
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据属性查询总数,查询条件使用等号
*
* @param ms
* @return
*/
public String existsWithProperty(MappedStatement ms) {
String propertyHelper = SelectPropertyProvider.class.getName();
Class<?> entityClass = getEntityClass(ms);

StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectCountExists(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
sql.append("<if test=\"@");
sql.append(propertyHelper);
sql.append("@existsWhereCondition(value, ");
sql.append(isNotEmpty());
sql.append(")");
sql.append("\">\n");
String entityClassName = entityClass.getName();
//通过实体类名获取运行时属性对应的字段
String ognl = new StringBuilder("${@")
.append(propertyHelper)
.append("@getColumnByProperty(@java.lang.Class@forName(\"")
.append(entityClassName)
.append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString();
sql.append(ognl + " = #{value}\n");
sql.append("</if>\n");
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据属性查询总数,查询条件使用等号
*
* @param ms
* @return
*/
public String selectCountByProperty(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
String propertyHelper = SelectPropertyProvider.class.getName();

StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectCount(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append("<where>\n");
sql.append("<if test=\"@");
sql.append(propertyHelper);
sql.append("@existsWhereCondition(value, ");
sql.append(isNotEmpty());
sql.append(")");
sql.append("\">\n");
String entityClassName = entityClass.getName();
//通过实体类名获取运行时属性对应的字段
String ognl = new StringBuilder("${@")
.append(propertyHelper)
.append("@getColumnByProperty(@java.lang.Class@forName(\"")
.append(entityClassName)
.append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString();
sql.append(ognl + " = #{value}\n");
sql.append("</if>\n");
// 逻辑删除的未删除查询条件
sql.append(SqlHelper.whereLogicDelete(entityClass, false));
sql.append("</where>");
return sql.toString();
}

/**
* 根据实体Class和属性名获取对应的表字段名
* @param entityClass 实体Class对象
* @param property 属性名
* @return
*/
public static String getColumnByProperty(Class<?> entityClass, String property) {
EntityTable entityTable = EntityHelper.getEntityTable(entityClass);
EntityColumn entityColumn = entityTable.getPropertyMap().get(property);
return entityColumn.getColumn();
}

/**
* 判断是否需要拼接 where 条件
* @param value
* @param notEmpty
* @return
*/
public static boolean existsWhereCondition(Object value, boolean notEmpty) {
boolean appendWhereCondition = true;
if (Objects.isNull(value)) {
log.warn("value is null! this will case no conditions after where keyword");
} else {
if (String.class.equals(value.getClass()) && notEmpty && StringUtil.isEmpty(value.toString())) {
// 如果 value 是 String 类型,则根据是否允许为空串做进一步校验来决定是否拼接 where 条件
appendWhereCondition = false;
}
}
return appendWhereCondition;
}
}
Loading

0 comments on commit bd10103

Please # to comment.