文章目录[隐藏]
目前项目当中使用mapper.xml文件方式对数据库进行操作,但是每个里边都有增/删/改/查,为了方便开发,把这些公共的代码提取出来,不用当做基类,不用每个Mapper文件都写了
准备工作:
1:数据库表
CREATE TABLE `t_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限ID', `type` int(11) NOT NULL COMMENT '权限类型', `name` varchar(255) NOT NULL COMMENT '权限名称', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='权限表';
2:准备实体类
public class TPermissionEntity { @PrimaryKey //下面步骤2中自定义注解 private Integer id;//权限ID private Integer type;//权限类型 private String name;//权限名称 //省略了get,set方法.... }
步骤1:编写工具类Tools:作用:用于驼峰和数据库字段的转换
因为类的名称用的是驼峰命名,所以这里需要转换一下
import java.util.regex.Matcher; import java.util.regex.Pattern; /* * 驼峰名称和下划线名称的相互转换 */ public class Tool { private static Pattern linePattern = Pattern.compile("_(\\w)"); /** 下划线转驼峰 */ public static String lineToHump(String str) { str = str.toLowerCase(); Matcher matcher = linePattern.matcher(str); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, matcher.group(1).toUpperCase()); } matcher.appendTail(sb); return sb.toString(); } private static Pattern humpPattern = Pattern.compile("[A-Z]"); /** 驼峰转下划线,效率比上面高 */ public static String humpToLine(String str) { Matcher matcher = humpPattern.matcher(str); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase()); } matcher.appendTail(sb); return sb.toString(); } }
步骤2:自定义两个注解,分别用于类字段的排除和字义主键
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Exclude { } @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface PrimaryKey { String value() default ""; }
步骤3:自定义动态sql生成类BaseSqlProvider<T>
作用:根据传入的对象动态获取表名和字段名生成动态的sql语句,再执行
@Insert,@Select,@update,@Delete是直接配置SQL语句,而@InsertProvider,@UpdateProvider,@SelectProvider,@DeleteProvider则是通过SQL工厂类及对应的方法生产SQL语句
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.jdbc.SQL; import com.example.demo.common.utils.Tool; public class BaseSqlProvider<T> { @Options public String add(T bean) { SQL sql = new SQL(); Class clazz = bean.getClass(); String tableName = clazz.getSimpleName(); String realTableName = Tool.humpToLine(tableName).replaceAll("_entity", "").substring(1); sql.INSERT_INTO(realTableName); List<Field> fields = getFields(clazz); for (Field field : fields) { field.setAccessible(true); String column = field.getName(); System.out.println("column:" + Tool.humpToLine(column)); sql.VALUES(Tool.humpToLine(column), String.format("#{" + column + ",jdbcType=VARCHAR}")); } return sql.toString(); } public String delete(T bean) { SQL sql = new SQL(); Class clazz = bean.getClass(); String tableName = clazz.getSimpleName(); String realTableName = Tool.humpToLine(tableName).replaceAll("_entity", "").substring(1); sql.DELETE_FROM(realTableName); List<Field> primaryKeyField = getPrimarkKeyFields(clazz); if (!primaryKeyField.isEmpty()) { for (Field pkField : primaryKeyField) { pkField.setAccessible(true); sql.WHERE(pkField.getName() + "=" + String.format("#{" + pkField.getName() + "}")); } } else { sql.WHERE(" 1= 2"); throw new RuntimeException("对象中未包含PrimaryKey属性"); } return sql.toString(); } private List<Field> getPrimarkKeyFields(Class clazz) { List<Field> primaryKeyField = new ArrayList<>(); List<Field> fields = getFields(clazz); for (Field field : fields) { field.setAccessible(true); PrimaryKey key = field.getAnnotation(PrimaryKey.class); if (key != null) { primaryKeyField.add(field); } } return primaryKeyField; } private List<Field> getFields(Class clazz) { List<Field> fieldList = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); Exclude key = field.getAnnotation(Exclude.class); if (key == null) { fieldList.add(field); } } return fieldList; } public String get(T bean) { SQL sql = new SQL(); Class clazz = bean.getClass(); String tableName = clazz.getSimpleName(); String realTableName = Tool.humpToLine(tableName).replaceAll("_entity", "").substring(1); sql.SELECT("*").FROM(realTableName); List<Field> primaryKeyField = getPrimarkKeyFields(clazz); if (!primaryKeyField.isEmpty()) { for (Field pkField : primaryKeyField) { pkField.setAccessible(true); sql.WHERE(pkField.getName() + "=" + String.format("#{" + pkField.getName() + "}")); } } else { sql.WHERE(" 1= 2"); throw new RuntimeException("对象中未包含PrimaryKey属性"); } System.out.println("getSql:"+sql.toString()); return sql.toString(); } public String update(T bean) { SQL sql = new SQL(); Class clazz = bean.getClass(); String tableName = clazz.getSimpleName(); String realTableName = Tool.humpToLine(tableName).replaceAll("_entity", "").substring(1); sql.UPDATE(realTableName); List<Field> fields = getFields(clazz); for (Field field : fields) { field.setAccessible(true); String column = field.getName(); if (column.equals("id")) { continue; } System.out.println(Tool.humpToLine(column)); sql.SET(Tool.humpToLine(column) + "=" + String.format("#{" + c<span style="color:transparent">本文来源gaodai#ma#com搞*!代#%^码网%</span>olumn + ",jdbcType=VARCHAR}")); } List<Field> primaryKeyField = getPrimarkKeyFields(clazz); if (!primaryKeyField.isEmpty()) { for (Field pkField : primaryKeyField) { pkField.setAccessible(true); sql.WHERE(pkField.getName() + "=" + String.format("#{" + pkField.getName() + "}")); } } else { sql.WHERE(" 1= 2"); throw new RuntimeException("对象中未包含PrimaryKey属性"); } System.out.println("updateSql:"+sql.toString()); return sql.toString(); } }
步骤4:编写BaseMapper基类接口
public interface BaseMapper<T> { //新增一条数据 @InsertProvider(method = "add",type=BaseSqlProvider.class) @Options(useGeneratedKeys=true) public int add(T bean); //根据主键删除一条数据 @DeleteProvider(method = "delete",type=BaseSqlProvider.class) public int delete(T bean); //根据主键获取一条数据 @SelectProvider(method = "get",type=BaseSqlProvider.class) public T get(T bean); //修改一条数据 @UpdateProvider(method = "update",type=BaseSqlProvider.class) public int update(T bean); }