Implementation of mybatis Extraction Base Class BaseMapper Addition Deletion and Modification

  • 2021-11-13 07:40:37
  • OfStack

Catalog Preparation: 1: Database Table 2: Prepare Entity Class Step 1: Write Tool Class Tools: Function: Conversion for Hump and Database Fields Step 2: Custom Two Annotations for Exclusion of Class Fields and Primary Key of Word Meaning Step 3: Custom Dynamic sql Generate Class BaseSqlProvider < T > Step 4: Write an example BaseMapper base class interface:

At present, the project uses mapper. xml files to operate the database, but each of them has added/deleted/changed/checked. In order to facilitate development, these common codes are extracted, not used as base classes, and each Mapper file is not written

Preparations:

1: Database tables


CREATE TABLE `t_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Authority ID',
  `type` int(11) NOT NULL COMMENT ' Permission type ',
  `name` varchar(255) NOT NULL COMMENT ' Permission name ',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT=' Permission table ';

2: Prepare Entity Classes


public class TPermissionEntity {
 
 @PrimaryKey // The following steps 2 Custom annotations in 
 private Integer id;// Authority ID
 
 private Integer type;// Permission type 
 private String name;// Permission name 
 
 // Omitted get,set Method ....
 
}

Step 1: Write the tool class Tools: Used for conversion of hump and database fields

Because the name of the class is named by hump, it is necessary to convert 1 here


import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
*  Conversion between hump name and underline name 
*/
public class Tool {
 
 private static Pattern linePattern = Pattern.compile("_(\\w)");
 /**  Underline to hump  */
 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]");
 /**  Hump turn underline , The efficiency is higher than above  */
 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();
 }
 
}

Step 2: Customize two annotations for class field exclusion and literal primary key


@Target({ElementType.FIELD})  
@Retention(RetentionPolicy.RUNTIME) 
public @interface Exclude {
 
}
@Target({ElementType.FIELD})  
@Retention(RetentionPolicy.RUNTIME)  
public @interface PrimaryKey {  
    String value() default "";  
} 

Step 3: Customize the dynamic sql generation class BaseSqlProvider < T >

Function: Dynamic sql statement is generated by dynamically obtaining table name and field name according to the passed-in object, and then executing

@ Insert, @ Select, @ update, @ Delete directly configure SQL statements, while @ InsertProvider, @ UpdateProvider, @ SelectProvider, @ DeleteProvider produce SQL statements through SQL factory classes and corresponding methods


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(" Object does not contain the PrimaryKey Attribute ");
  }
 
  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(" Object does not contain the PrimaryKey Attribute ");
  }
  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(" Object does not contain the PrimaryKey Attribute ");
  }
  System.out.println("updateSql:"+sql.toString());
  return sql.toString();
 
 } 
}

Step 4: Write the BaseMapper base class interface


public interface BaseMapper<T> {
 
        // Add 1 Bar data 
 @InsertProvider(method = "add",type=BaseSqlProvider.class)
 @Options(useGeneratedKeys=true)
 public int add(T bean);
 
        // Delete by primary key 1 Bar data 
 @DeleteProvider(method = "delete",type=BaseSqlProvider.class)
 public int delete(T bean);
 
        // Obtain according to primary key 1 Bar data 
 @SelectProvider(method = "get",type=BaseSqlProvider.class)
 public T get(T bean);
 
        // Modify 1 Bar data 
 @UpdateProvider(method = "update",type=BaseSqlProvider.class)
 public int update(T bean);
 
}

Explanation: type in the @ InsertProvider annotation indicates the custom SQL factory class, method is the corresponding method in the factory class, and the method returns the sql statement of the other party

At this point, the base class and its configuration are completed. Next, you can use

Examples:

Write an TPermissionMapper interface, implement BaseMapper class, and pass in a generic parameter, this TPermissionMapper interface has already had, BaseMapper basic add/delete/change/check function. At the same time, TPermissionMapper can also write its own unique method and mapper. xml file to expand the function


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

Application in controller:


@Controller
public class LoginController {
 
 @Autowired
 private TPermissionMapper tPermissionMapper;
 
        // Add 
 @ResponseBody
 @RequestMapping(value = "/add")
 public Integer add() {
  TPermissionEntity permissionEntiry = new TPermissionEntity();
  permissionEntiry.setName("test");
  permissionEntiry.setType(3);
  Integer num = tPermissionMapper.add(permissionEntiry);
  return num;
 }
 
        // Modify 
 @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;
 }
 
        // Query 
 @ResponseBody
 @RequestMapping(value = "/query")
 public TPermissionEntity query() {
  TPermissionEntity tPermissionEntity = new TPermissionEntity();
  tPermissionEntity.setId(23);
  tPermissionEntity= (TPermissionEntity) tPermissionMapper.get(tPermissionEntity);
  return tPermissionEntity;
 }
 
        // Delete 
 @ResponseBody
 @RequestMapping(value = "/delete")
 public Integer delete() {
  TPermissionEntity permissionEntiry = new TPermissionEntity();
  permissionEntiry.setId(22);
  Integer num = tPermissionMapper.delete(permissionEntiry);
  return num;
 }
}

Related articles: