当我们学习了mybatis后,我们在感叹mybatis的强大的同时,可能也会为重复的sql而感到厌烦,于是有了MybatisPlus 与 TKMybatis,对于还没用过的可能还不习惯,于是便自己想整一个简单的mapper增强,里面放置一些通用的方法,基于MybatisPlus的一些启发来实现,首先不管这些方法在mapper的具体实现,先考虑将这些通用方法在service与mapper层提取出来
我们首先定义BaseService与BaseMpper接口:
/**
* service层公用方法接口
* @param <T>
*/
public interface BaseService<T> {
T getById(int id);
List<T> getByCondition(Map paramsMap);
List<T> getByCondition(T model);
Long insert(T model);
Long updateById(T model);
Long deleteById(int id);
Boolean existById(int id);
}
/**
* 基础baseMapper,提取mapper公用的方法
*
* @param <T>
*/
public interface BaseMapper<T> {
T getById(@Param("id") int id);
List<T> getByCondition(Map paramsMap);
List<T> getByCondition(T model);
Long insert(T model);
Long updateById(T model);
Long deleteById(@Param("id") int id);
Boolean existById(@Param("id") int id);
}
这里mapper层的方法肯定是用注解的方式去解析sql,我们先不管 mapper层方法如何实现,我们来看下如此定义,我们去使用有什么弊端,在我们具体的业务模块中,比如说用户模块中,我们需要分别写接口UserService与UserMapper去继承上面的接口以使用他们的方法,然后写UserService的实现类UserServiceImpl,那我们在UserServiceImpl中反而要调用UserMapper对方法一一实现,显得繁琐,那我们能不能将UserServiceImpl中的具体实现提取出来呢?我们定义一个抽象类BaseServiceImpl实现接口BaseService,使得所有的ServiceImpl都继承它,如下:
/**
* 定义公用方法的的实现类,业务层只需继承就可以调用
* @param <T> 实体类泛型
* @param <M> Mapper泛型
*/
public abstract class BaseServiceImpl<T,M extends BaseMapper<T>> implements BaseService<T> {
@Autowired
private M m;
@Override
public List<T> getByCondition(T model){return m.getByCondition(model);}
@Override
public List<T> getByCondition(Map model){return m.getByCondition(model);}
@Override
public T getById(int id){ return m.getById(id);}
@Override
public Long insert(T model){ return m.insert(model);}
@Override
public Long updateById(T model){return m.updateById(model);}
@Override
public Long deleteById(int id){return m.deleteById(id);}
@Override
public Boolean existById(int id){return m.existById(id);}
}
注意类上面的泛型,我们将Mapper以泛型的形式传递进来,然后通过@Autowrid注解从spring容器注入,在这里做这些方法在业务层的具体实现,那我们在具体模块中就只需要继承就ok了,如下:
/**
* 此处只需要定义mapper层和service层 方法名 不同的方法
* 同名的方法抽象到 CommonUserMethodInterface 接口
*/
public interface UserMapper extends BaseMapper<User>{
}
-----------------------------------------------------------------------------------
/**
* 此处只需要定义service层方法名 和 mapper不同的方法
* 同名的方法抽象到 CommonUserMethodInterface 接口
*/
public interface UserService extends BaseService<User>{
}
------------------------------------------------------------------------------------
@Service
public class UserServiceImpl extends BaseServiceImpl<User,UserMapper> implements UserService{
}
然后我们在控制层就可以调用到我们的提取到的公用方法了,省掉了我们以前我们在每个模块的业务层去实现这些方法,然后我们来看如何去加载我们的BaseMapper,mybatis提供了一个 @Lang 的注解,允许我们去自定义解析sql的驱动,如下,我们需要定义我们自己的sql驱动
/**
* 基础baseMapper,提取mapper公用的方法
* 参数为实体类或者map的不能用 @Param 注解
* @param <T>
*/
public interface BaseMapper<T> {
/**
* 根据id查询
* @param id
* @return
*/
@Lang(BaseMapperDriver.class)
@Select("SELECT ${columns} FROM ${table} where ${id} = #{id}")
T getById(@Param("id") int id);
/**
* 条件查询,参数为map,
* 注意: 不能使用 @Param 注解,key的值必须为实体类的字段名
* @return
*/
@Lang(BaseMapperDriver.class)
@Select("SELECT ${columns} FROM ${table} where 1=1 ${conditions}")
List<T> getByCondition(Map paramsMap);
/**
* 优先使用此方法做查询
* 条件查询,参数为实体类,不能使用 @Param 注解
* @return
*/
@Lang(BaseMapperDriver.class)
@Select("SELECT * FROM ${table} where 1=1 ${conditions} ")
List<T> getByCondition(T model);
/**
* 插入
* @param model
* @return
*/
@Lang(BaseMapperDriver.class)
@Insert("INSERT INTO ${table} ${keys} values ${values}")
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
Long insert(T model);
/**
* 根据id 修改
* @param model
* @return
*/
@Lang(BaseMapperDriver.class)
@Update("UPDATE ${table} ${sets} WHERE ${id}=#{id}")
Long updateById(T model);
/**
* 删除
* @param id
* @return
*/
@Lang(BaseMapperDriver.class)
@Delete("DELETE FROM ${table} WHERE ${id}=#{id}")
Long deleteById(@Param("id") int id);
/**
* 判断是否存在
* @param id
* @return
*/
@Lang(BaseMapperDriver.class)
@Select("SELECT COUNT(1) FROM ${table} WHERE ${id}=#{id}")
Boolean existById(@Param("id") int id);
}
在定义驱动之前,我们需要重写mybatis的一些配置类:
将配置类注入工厂
@Configuration
public class DataConfig {
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
@Bean
public SqlSessionFactoryBean configSqlSessionFactoryBean(DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources(mapperLocations));// 设置mapper文件扫描路径
bean.setConfiguration(new MybatisConfig());
return bean;
}
}
在配置类的构造方法中注入 MybatisMapperRegistry
/**
* 重写mybatis的 Configuration
*/
public class MybatisConfig extends Configuration {
protected final MapperRegistry mapperRegistry;
public MybatisConfig(){
super();
this.mapperRegistry = new MybatisMapperRegistry(this);
this.mapUnderscoreToCamelCase = true;
}
@Override
public MapperRegistry getMapperRegistry() {
return this.mapperRegistry;
}
@Override
public void addMappers(String packageName, Class<?> superType) {
this.mapperRegistry.addMappers(packageName, superType);
}
@Override
public void addMappers(String packageName) {
this.mapperRegistry.addMappers(packageName);
}
@Override
public <T> void addMapper(Class<T> type) {
this.mapperRegistry.addMapper(type);
}
@Override
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
@Override
public boolean hasMapper(Class<?> type) {
return this.mapperRegistry.hasMapper(type);
}
}
在MybatisMapperRegistry中主要是在addMapper方法中捕获当前的mapper类,在我们自定义sql驱动需要用到
/**
* 自定义mapperRegistry
*/
public class MybatisMapperRegistry extends MapperRegistry {
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();
private Configuration config;
private static Class<?> currentMapper;
public MybatisMapperRegistry(Configuration config) {
super(config);
this.config = config;
}
public static Class<?> getCurrentMapper() {
return currentMapper;
}
@Override
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (this.hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
this.knownMappers.put(type, new MapperProxyFactory(type));
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
currentMapper = type;
parser.parse();
currentMapper=null;
loadCompleted = true;
} finally {
if (!loadCompleted) {
this.knownMappers.remove(type);
}
}
}
}
@Override
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
@Override
public <T> boolean hasMapper(Class<T> type) {
return this.knownMappers.containsKey(type);
}
@Override
public Collection<Class<?>> getMappers() {
return Collections.unmodifiableCollection(this.knownMappers.keySet());
}
@Override
public void addMappers(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
Iterator var5 = mapperSet.iterator();
while(var5.hasNext()) {
Class<?> mapperClass = (Class)var5.next();
this.addMapper(mapperClass);
}
}
@Override
public void addMappers(String packageName) {
this.addMappers(packageName, Object.class);
}
}
然后我们去看如何自定义sql解析器
自定义类 继承XMLLanguageDriver 实现LanguageDriver , 在LanguageDriver中有三个方法,在XMLLanguageDriver中对三个方法做了简单的实现
1. ParameterHandler createParameterHandler(MappedStatement var1, Object var2, BoundSql var3);
该方法用于mybatis参数填充处理,在sql执行之前会被调用
2.SqlSource createSqlSource(Configuration var1, XNode var2, Class<?> var3);
该方法用于解析xml中的sql
3.SqlSource createSqlSource(Configuration var1, String var2, Class<?> var3);
该方法用于解析注解中的sql
我们需要重写的就是方法3,基本原理就是获取当前mapper接口的泛型,这个泛型一般都为实体类,我们在这个实体类上添加注解,标记实体类与数据库中表的对应,我添加的注解如下:
/**
* 注解到实体类属性上,标记属性对应的列名
* 只有 有此注解的才会被解析进sql
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
}
------------------------------------------------------
/**
* 指定主键
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
String name() default "";
}
----------------------------------------------------------
/**
* 查询时默认查询所有注解有 @column 的属性对应的字段
* 注解到实体类属性上,标记查询时不被查询的属性
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoredColumn {
}
---------------------------------------------------------
/**
* 指定表名
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String name();
}
-----------------------------------------------------------
/**
* 是否使用父类属性
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseParent {
}
重写方法如下:
我们对获取到的泛型,实际就是实体类,对它的属性进行遍历,通过属性上的注解获取属性在数据库对应的字段,然后对sql进行拼接替换
/**
* 自定义 基础mapper查询驱动
*
*/
public class BaseMapperDriver extends XMLLanguageDriver implements LanguageDriver {
@Override
public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
/* 对sql进行解析处理 */
BaseMapperDriverResolver baseMapperDriverResolver = new BaseMapperDriverResolver();
script = baseMapperDriverResolver.createSqlSource(configuration,script);
return super.createSqlSource(configuration, script , parameterType);
}
}
--------------------------------------------------------------------------------------
public class BaseMapperDriverResolver extends DriverResolver {
public String createSqlSource(Configuration configuration, String script){
//获取当前mapper
Class<?> mapperClass = null;
if(configuration instanceof MybatisConfig){
mapperClass = MybatisMapperRegistry.getCurrentMapper();
if(mapperClass == null){
throw new BaseException("解析SQL出错");
}
}
//处理SQL
if(mapperClass!=null) {
/* 获取当前mapper接口上的泛型,这个泛型实际上对应着实体类 */
Class<?> generics = getMapperGenerics(mapperClass);
String newScript = super.commonCreateSqlSource(generics, script);
StringBuilder sb = new StringBuilder( "<script>");
sb.append(newScript);
sb.append("</script>");
script = sb.toString();
}
return script;
}
}
public abstract class DriverResolver implements BaseResolverInterface {
static final String tablePattern = "\\$\\{table\\}";
static final String idPattern = "\\$\\{id\\}";
static final String columnsPattern = "\\$\\{columns\\}";
static final String keysPattern = "\\$\\{keys\\}";
static final String valuesPattern = "\\$\\{values\\}";
static final String setsPattern = "\\$\\{sets\\}";
static final String conditionPattern = "\\$\\{conditions\\}";
/**
* 判断是否是select方法
* @param script
* @return
*/
public boolean isSelect(String script){
Matcher matcher = Pattern.compile("[selectSELECT]{6}").matcher(script);
/* 判断是否是select方法 */
if(matcher.find()){
return true;
} else{
return false;
}
}
/**
* 判断是否是插入语句
* @param script
* @return
*/
public boolean isInsert(String script){
Matcher matcher = Pattern.compile("[insertINSERT]{6}").matcher(script);
/* 判断是否是insert方法 */
if(matcher.find()){
return true;
} else{
return false;
}
}
/**
* 判断是否更新语句
* @param script
* @return
*/
public boolean isUpdate(String script){
Matcher matcher = Pattern.compile("[updateUPDATE]{6}").matcher(script);
/* 判断是否是update方法 */
if(matcher.find()){
return true;
} else{
return false;
}
}
/**
* 判断是否是删除语句
* @param script
* @return
*/
public boolean isDelete(String script){
Matcher matcher = Pattern.compile("[deleteDELETE]{6}").matcher(script);
/* 判断是否是delete方法 */
if(matcher.find()){
return true;
} else{
return false;
}
}
/**
* 判断sql是否含有 ${table}
* @param script
* @return
*/
public boolean hasTable(String script){
Matcher matcher = Pattern.compile(tablePattern).matcher(script);
return matcher.find();
}
/**
* 判断sql是否含有 ${id}
* @param script
* @return
*/
public boolean hasId(String script){
Matcher matcher = Pattern.compile(idPattern).matcher(script);
return matcher.find();
}
/**
* 判断sql是否含有 ${columns}
* @param script
* @return
*/
public boolean hasColumns(String script){
Matcher matcher = Pattern.compile(columnsPattern).matcher(script);
return matcher.find();
}
/**
* 判断sql是否含有 ${keys}
* @param script
* @return
*/
public boolean hasKeys(String script){
Matcher matcher = Pattern.compile(keysPattern).matcher(script);
return matcher.find();
}
/**
* 判断sql是否含有 ${values}
* @param script
* @return
*/
public boolean hasValues(String script){
Matcher matcher = Pattern.compile(valuesPattern).matcher(script);
return matcher.find();
}
/**
* 判断sql是否含有 ${sets}
* @param script
* @return
*/
public boolean hasSets(String script){
Matcher matcher = Pattern.compile(setsPattern).matcher(script);
return matcher.find();
}
/**
* 判断是否是条件查询
* @param script
* @return
*/
public boolean hasConditions(String script){
Matcher matcher = Pattern.compile(conditionPattern).matcher(script);
return matcher.find();
}
/**
* 获取mapper接口的泛型
* @param mapperClass
* @return
*/
public Class<?> getMapperGenerics(Class<?> mapperClass){
/*获取mapperClass接口的类型*/
Type[] types = mapperClass.getGenericInterfaces();
ParameterizedType parameterizedType = (ParameterizedType)types[0];
Type[] types1 = parameterizedType.getActualTypeArguments();
return (Class<?>)types1[0];
/* 多个泛型需要遍历 */
/*Class<?>[] classes = new Class[types.length];
for(Type type:types){
ParameterizedType parameterizedType = (ParameterizedType)type;
Type[] types1 = parameterizedType.getActualTypeArguments();
classes[0] = (Class<?>) types1[0];
}
return classes;*/
}
/**
* 获取实体类所有的属性
* @param generics
* @return
*/
public List<Field> getFieldList(Class<?> generics){
/* 获取所有的字段 */
//获取所有属性的合集
List<Field> fieldList = new ArrayList();
/* 判断是否有该注解 */
if(generics.isAnnotationPresent(UseParent.class)){
/* 添加父类的所有字段 */
fieldList.addAll(Arrays.asList(generics.getSuperclass().getDeclaredFields()));
}
/* 添加本类所有字段 */
fieldList.addAll(Arrays.asList(generics.getDeclaredFields()));
return fieldList;
}
/**
* 替换insert与update的列名
* 只会拼接有 @column 注解的字段
* @param field
* @return
*/
@Override
public String setKeys(Field field){
/* 获取实体类的字段名 */
String __field = field.getName();
String __column;
if (field.isAnnotationPresent(Column.class)) {
/* 获取注解中表的列名 */
__column = field.getAnnotation(Column.class).name();
/* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
if ("".equals(__column)) {
__column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
}
String keysTemp = "<if test=\"__field != null\"> __column, </if>";
//拼接
return keysTemp.replaceAll("__field", __field).replaceAll("__column", __column);
}
return "";
}
/**
* 替换insert与update的实体类字段, keys的value
* 只会拼接有 @column 注解的字段
* @param field
* @return
*/
@Override
public String setValues(Field field){
if (field.isAnnotationPresent(Column.class)) {
String valuesTemp = "<if test=\"__field != null\"> #{__field} , </if>";
return valuesTemp.replaceAll("__field", field.getName());
}
return "";
}
/**
* 替换update的 set集合
* 只会拼接有 @column 注解的字段
* @param field
* @return
*/
@Override
public String setSets(Field field){
/* 获取实体类的字段名 */
String __field = field.getName();
String __column;
String temp = "";
if(field.isAnnotationPresent(Column.class)) {
/* 获取注解中表的列名 */
__column = field.getAnnotation(Column.class).name();
/* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
if ("".equals(__column)) {
__column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
}
temp = "<if test=\"__field != null\"> __column=#{__field} </if>";
//拼接
temp.replaceAll("__field", __field).replaceAll("__column", __column);
}
return temp;
}
/**
* 设置需要查询的列名
* @param field
* @return
*/
@Override
public String setColumns(Field field) {
String temp = "";
boolean ignoredColumn = false;
/* 获取实体类的字段名 */
String __field = field.getName();
String __column = "";
if (field.isAnnotationPresent(Column.class)) {
/*有此注解则被忽略*/
if (field.isAnnotationPresent(IgnoredColumn.class)) {
ignoredColumn = true;
}
/* 获取注解中表的列名 */
__column = field.getAnnotation(Column.class).name();
} else if(field.isAnnotationPresent(Id.class)){
/*有此注解则被忽略*/
if (field.isAnnotationPresent(IgnoredColumn.class)) {
ignoredColumn = true;
}
/* 获取注解中表的列名 */
__column = field.getAnnotation(Id.class).name();
} else {
ignoredColumn = true;
}
if(!ignoredColumn){
/* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
if ("".equals(__column)) {
__column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
}
temp = " __column __field , ";
temp = temp.replaceAll("__column", __column).replaceAll("__field",__field);
}
return temp;
}
/**
* 替换表名
* @param generics
* @return
*/
@Override
public String setTable(Class<?> generics){
/* 若未添加注解,直接返回 */
if(!generics.isAnnotationPresent(Table.class)){
throw new BaseException("类:"+generics.getName()+"未添加注解 " + Table.class.getName());
}
/* 获取注解上的表名 */
String tableName = generics.getAnnotation(Table.class).name();
/* 若table注解没有传值,使用类名进行变换 */
if("".equals(tableName)){
tableName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, generics.getName());
}
/* 替换表名 */
return tableName;
}
/**
* 替换主键
* @param field
* @return
*/
@Override
public String setId(Field field){
String __id = "";
if (field.isAnnotationPresent(Id.class)) {
/* 获取注解中表的列名 */
__id = field.getAnnotation(Id.class).name();
/* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
if("".equals( __id )){
__id = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName());
}
}
return __id;
}
/**
* 拼接条件查询动态sql
* @param field
* @return
*/
@Override
public String setConditions(Field field){
boolean isPass = false;
String temp = "";
/* 获取实体类的字段名 */
String __field = field.getName();
String __column = "";
if (field.isAnnotationPresent(Id.class)) {
/* 获取注解中表的列名 */
__column = field.getAnnotation(Id.class).name();
} else if(field.isAnnotationPresent(Column.class)){
/* 获取注解中表的列名 */
__column = field.getAnnotation(Column.class).name();
} else {
/* 没有注解标记的跳过 */
isPass = true;
}
if(!isPass){
/* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
if("".equals(__column)){
__column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
}
temp = "<if test=\"__field != null\"> and __column=#{__field} </if>";
//拼接
temp = temp.replaceAll("__field", __field).replaceAll("__column", __column);
}
return temp;
}
/**
* 通用替换拼接sql
* @param generics
* @param script
* @return
*/
public String commonCreateSqlSource(Class<?> generics,String script) {
StringBuilder id = new StringBuilder();
StringBuilder columns = new StringBuilder();
StringBuilder keys = new StringBuilder();
StringBuilder values = new StringBuilder();
StringBuilder sets = new StringBuilder();
StringBuilder conditions = new StringBuilder();
List<Field> fieldList = getFieldList(generics);
//遍历所有的属性
for (Field field : fieldList) {
if(hasId(script)){
/* 获取id */
id.append(setId(field));
}
if(hasColumns(script)){
/* 拼接查询的列名 */
columns.append(setColumns(field));
}
if(hasKeys(script)){
/* 拼接insert和update的keys */
keys.append(setKeys(field));
}
if(hasValues(script)){
/* 拼接insert和update的values */
values.append(setValues(field));
}
if(hasSets(script)){
/* 拼接update的sets */
sets.append(setSets(field));
}
if (hasConditions(script)){
conditions.append(setConditions(field));
}
}
/* 判断是否需要替换 ${table} 表名不需要遍历 */
if(hasTable(script)){
String table = setTable(generics);
script = script.replaceAll(tablePattern,table);
}
/* 判断是否需要替换 ${id} */
if (hasId(script)){
script = script.replaceAll(idPattern,id.toString());
}
/* 判断是否需要替换 ${columns} */
if (hasColumns(script)){
StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
sb.append(columns);
sb.append("</trim> ");
script = script.replaceAll(columnsPattern,sb.toString());
}
/* 判断是否需要替换 ${keys} */
if (hasKeys(script)){
StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
sb.append(keys);
sb.append("</trim> ");
script = script.replaceAll(keysPattern,sb.toString());
}
/* 判断是否需要替换 ${values} */
if (hasValues(script)){
StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
sb.append(values);
sb.append("</trim> ");
script = script.replaceAll(valuesPattern,sb.toString());
}
/* 判断是否需要替换 ${sets} */
if (hasSets(script)){
StringBuilder sb = new StringBuilder("<set> <trim suffixOverrides=\",\"> ");
sb.append(sets);
sb.append("</trim> </set>");
script = script.replaceAll(setsPattern,sb.toString());
}
/* 判断是否需要添加查询条件 */
if (hasConditions(script)){
StringBuilder sb = new StringBuilder();
sb.append(conditions);
script = script.replaceAll(conditionPattern,sb.toString());
}
return script;
}
}
public interface BaseResolverInterface {
String setTable(Class<?> entityClazz);
String setId(Field field);
String setColumns(Field field);
String setKeys(Field field);
String setValues(Field field);
String setSets(Field field);
String setConditions(Field field);
}
gitee地址:https://gitee.com/dchenleilei/springboot/tree/master