mybatis抽取基類BaseMapper增刪改查的實現

目前項目當中使用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("#{" + column + ",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);
 
}

說明:@InsertProvider註解中的type指明自定義的SQL工廠類,method是工廠類裡對應的方法,方法返回的是對方的sql語句

到這裡基類以及它的配置就完成瞭,接下來,可以使用瞭

舉例:

編寫一個TPermissionMapper接口,實現BaseMapper類,並傳入一個泛型參數,此時這個TPermissionMapper接口已經具備瞭,BaseMapper中基本的增/刪/改/查功能.同時TPermissionMapper還可以再寫自己獨有的方法和mapper.xml文件對功能進行擴展

public interface TPermissionMapper extends BaseMapper<TPermissionEntity>{
 
 //List<TPermissionEntity> queryByPage();
 
}

在controller當中的應用:

@Controller
public class LoginController {
 
 @Autowired
 private TPermissionMapper tPermissionMapper;
 
        //新增
 @ResponseBody
 @RequestMapping(value = "/add")
 public Integer add() {
  TPermissionEntity permissionEntiry = new TPermissionEntity();
  permissionEntiry.setName("test");
  permissionEntiry.setType(3);
  Integer num = tPermissionMapper.add(permissionEntiry);
  return num;
 }
 
        //修改
 @ResponseBody
 @RequestMapping(value = "/update")
 public Integer update() {
  TPermissionEntity permissionEntiry = new TPermissionEntity();
  permissionEntiry.setId(23);
  permissionEntiry.setName("test");
  permissionEntiry.setType(3);
  Integer num = tPermissionMapper.update(permissionEntiry);
  return num;
 }
 
        //查詢
 @ResponseBody
 @RequestMapping(value = "/query")
 public TPermissionEntity query() {
  TPermissionEntity tPermissionEntity = new TPermissionEntity();
  tPermissionEntity.setId(23);
  tPermissionEntity= (TPermissionEntity) tPermissionMapper.get(tPermissionEntity);
  return tPermissionEntity;
 }
 
        //刪除
 @ResponseBody
 @RequestMapping(value = "/delete")
 public Integer delete() {
  TPermissionEntity permissionEntiry = new TPermissionEntity();
  permissionEntiry.setId(22);
  Integer num = tPermissionMapper.delete(permissionEntiry);
  return num;
 }
}

到此這篇關於mybatis抽取基類BaseMapper增刪改查的實現的文章就介紹到這瞭,更多相關mybatis BaseMapper增刪改查內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: