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!