目前项目当中使用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增删改查内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!