1. 程式人生 > >mybatis抽取基類BaseMapper(通用增/刪/改/查)

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;
	}

}