众所周知,Mybatis的横空出世,打破了持久层暗箱操作的时代(Hibernate),相对于Hibernate而言,
1. Mybatis对SQL是透明的;
2. 程序员不仅可以手动写特定的SQL(舒服呀!),还能通过SQL优化性能,一箭双雕;
3. 具有高性能,映射,存储的特点,是一个比较不错的半自动化持久层的架构。
然而随着需求的剧增,Mapper文件中需要写的基本CRUD很多,想一想,n个实体,那得需要写多少个Mapper呀,可见,大大降低了开发的效率(又要脱发了,又要加班啦!!!),俗话说:上有政策,下有对策。写的一种方法吧(不喜勿喷呀,,,仅做参考哦),站在巨人的肩膀上哈!!!
现在开源的框架有通用Mapper、MP等等,都可以实现的哈,大家可以去官网看看哈,这里就不多啰嗦啦!
下面是方法的介绍哈
- SpringBoot的基本环境的搭建以及配置
- 集成Mybatis
- 建库,建表
- 实体类
- 编写SQL工厂(CURDTemplateSQL模板工厂、自己编写的工厂)、注解类、工具类等
- sevice层、实现层、控制层
- 用postman测试
现在直接上代码啦!
基本的环境就不说了(相信大家都会哈!)
首先编写SQL工厂,提供所需的SQL语句(可以按照自己的风格哈!!!)
ublic class BaseSqlProvider<T> {
@Options//一些数据库的默认规则
public String add(T bean) {
SQL sql = new SQL();
//返回 此对象的运行时类的类对象
Class clazz = bean.getClass();
//返回 实体类 的类名
String EnityName = clazz.getSimpleName();
//test
System.out.println("BaseSqlProvider_32 --->EnityName " + EnityName);
String realTableName = Tool.humpToLine(EnityName).replaceAll("_entity", "").substring(1);
//test
System.out.println("realTableName_39 --->" + realTableName);
sql.INSERT_INTO(realTableName);
//遍历当前实体类映射数据库中的每一个字段
List<Field> fields = getFields(clazz);
for (Field field : fields) {
//字段的访问权限
field.setAccessible(true);
//字段名称
String column = field.getName();
/*
* 此处有一个问题待解决:字段的类型
*/
//获取字段的类型
//Type type = field.getGenericType();
// sql.VALUES(Tool.humpToLine(column), String.format("#{" + column + ",jdbcType="+ VARCHAR+ "}"));
//test
System.out.println("column:" + Tool.humpToLine(column));
//这里不需要声明 字段的类型,(可以添加的)
sql.VALUES(Tool.humpToLine(column), String.format("#{" + column + "}"));
}
//打印SQL
System.out.println("添加SQL " + sql.toString());
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);
//获取标注有@primarykey主键字段
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属性");
}
//打印SQL
System.out.println("删除SQL " + sql.toString());
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("查询SQL:"+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")) {
//终止本次循环,继续下一次循环
//不能使用break,否则会跳出整个for循环
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("更新操作: "+sql.toString());
return sql.toString();
}
}
提供基本的BaseMapper
/*
* 说明:@InsertProvider注解中的type指明自定义的SQL工厂类,method是工厂类里对应的方法,方法返回的是对方的sql语句
*/
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);
}
提供自己的mapper,并继承basemapper
/*
* 编写myMapper 接口,实现BaseMapper类,并传入一个泛型参数,此时这个myMapper接口已经具备了,
* BaseMapper中基本的增/删/改/查功能.同时TPermissionMapper还可以再写自己独有的方法和mapper.xml文件对功能进行扩展
*/
public interface myMapper extends BaseMapper<TPermissionEntity>{
}
注解类
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Exclude {
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PrimaryKey {
}
然后大家自己可以写service、controller 层进行测试哈,或者用postman都可以的!!!