大概
- 对于一些业务逻辑操作,每个实体类会有很多重复的操作,如学生管理,教师管理,书本管理等都会需要用到增删查改,就会出现大量的重复代码,不优雅,不美观,没逼格。
- 所以 我想法呢 就是将那些重复的代码抽出来,放到一个公共的mapper中(学过mybatis的应该能明白吧),并慢慢加上分页、级联。
- 实现呢就是封装一个 base 层 ,将需要的数据在 service 层中处理好后 传给 baseDao 的接口,然后在baseMapper 中使用动态语句来实现对数据库的操作
- 当然如果大牛觉得此方法有什么不妥 完全可以说出来,我可以调整,如果这个结构不妥,不符合java或者编程上的某些高深的思想,那就当是另外一种方式来学习吧。毕竟都是一种实现方式,没有最好的,只有慢慢发掘更好,让其更完善
先简单实现一些公用方法.当前结构如下图:
首先写 service 层接口
public interface IBaseService <T>{
void del( int id );
List<T> queryAll();
int add( T t );
void update ( T t );
}
service 层实现类 大部分在这里下功夫了
package com.hututu.xinyong.base.serviceImpl;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.javassist.CodeConverter.ArrayAccessReplacementMethodNames;
import org.springframework.stereotype.Service;
import com.hututu.commons.Tool;
import com.hututu.xinyong.base.service.IBaseService;
import com.hututu.xinyong.dao.IBaseDao;
@Service
public abstract class BaseService<T> implements IBaseService<T>{
//提供一个抽象方法 当前类的子类需要提供具体实现类的 Dao
public abstract IBaseDao<T> getBaseDao();
//提供一个抽象方法 当前类的子类需要提供 entity的 Class 对象
public abstract Class<T> getClasss();
public Class<T> clsss;
{
clsss = getClasss();
}
/**
* 根据 id 查找一个对象
*/
@Override
public T queryOne(Long id) {
String name = getTableName();
Map<Object, Object> map = getBaseDao().queryOne(name,id).get(0);
T t = hashMapToEntity(map);
return t;
}
/**
* 查找所有对象
*/
@Override
public List<T> queryAll() {
List<T> ts = new ArrayList<>();
String name = clsss.getSimpleName().toLowerCase();
List<HashMap<Object, Object>> list = getBaseDao().queryAll( name );
for (HashMap<Object, Object> hashMap : list) {
ts.add( hashMapToEntity( hashMap ) );
}
return ts;
}
/**
* 添加一个 对象
*/
@Override
public int add(T t) {
//获取表名
String tableName = getTableName();
List<String> clumus= new ArrayList<>();
List<Object> list= new ArrayList<>();
//将参数放入数组中
for (Field field : getAllFields()) {
field.setAccessible(true);//权限
try {
if ( field.get(t) == null ) {
continue;
}
list.add(field.get(t));
clumus.add(field.getName());
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
clumus.add("create_time");
clumus.add("update_time");
clumusToline(clumus);
list.add(new Date());
list.add(new Date());
return getBaseDao().add( tableName ,clumus.toArray(),list.toArray() );
}
/**
* 更新一个对象
*/
@Override
public void update(T t) {
Long id = 0l;
String tableName = getTableName();
List<Object> list= new ArrayList<>();
for (Field field : t.getClass().getDeclaredFields()) {
field.setAccessible(true);//权限
try {
if ( field.get(t) == null ) {
continue;
}
if (("id").equals( field.getName()) ) {
id = (Long) field.get(t);
continue ;
}
//拼接成 :变量名='值' 的形式
list.add( field.getName()+"="+ "'" + field.get(t) + "'" );
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
getBaseDao().update( id, tableName , list.toArray() );
}
public Field[] getAllFields(){
Class clazz = clsss;
List<Field> fieldList = new ArrayList<>();
while (clazz != null){
Field[] Filelds = clazz.getDeclaredFields();
for (Field field : Filelds) {
if(!fieldList.contains(field)) {
fieldList.add(field);
}
}
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
System.out.println(fieldList.size());
fieldList.toArray(fields);
return fields;
}
/**
* 根据id 删除 一个对象
*/
@Override
public void del(Long id) {
String name = clsss.getSimpleName();
name = name.toLowerCase();
getBaseDao().del(name, id);
}
private String getTableName() {
String name=clsss.getSimpleName();
String tableName = Tool.humpToLine2(name);
return tableName;
}
private T hashMapToEntity(Map<Object, Object> map) {
return injectBean(clsss,map);
}
//使用泛型
public static final <T> T injectBean(Class<T> beanClass,Map parasMap) {
T bean = null;
try {
//通过反射生成对象
bean = beanClass.newInstance();
//还可以用Class.forName生成对象
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//获取类的方法
Method[] methods = beanClass.getMethods();
int len = methods.length;
for(int i = 0; i < len; ++i) {
Method method = methods[i];
String methodName = method.getName();
//如果方法名是set开头的且名字长度大于3的
if(methodName.startsWith("set") && methodName.length() > 3) {
//获取方法的参数类型
Class[] types = method.getParameterTypes();
//只有一个参数的方法才继续执行
if(types.length == 1) {
//取字段名且让其首字母小写
String attrName = firstCharToLowerCase(methodName.substring(3));
//map中是否有属性名
attrName=Tool.humpToLine2(attrName);
if(parasMap.containsKey(attrName)) {
Object value = parasMap.get(attrName);
try {
//通过反射的方式执行bean的mothod方法,在这里相当于执行set方法赋值
method.invoke(bean, new Object[]{value});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
return bean;
}
//取字段名且让其首字母小写
public static String firstCharToLowerCase(String substring) {
if (substring!=null&& substring.charAt(0)>='A' && substring.charAt(0)<='Z'){
char[] arr = substring.toCharArray();
arr[0] = (char)(arr[0] + 32);
return new String(arr);
}else {
return substring;
}
}
public void clumusToline(List<String> clumus) {
for(int i=0;i<clumus.size();i++) {
clumus.set(i, Tool.humpToLine2(clumus.get(i)));
}
}
}
接下来是 Dao 层接口
- mybatis 中 一个多个参数时需要用 @Param(” xxx “) 设置别名以区分
package com.hututu.xinyong.dao;
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface IBaseDao <T> {
List<HashMap<Object, Object>> queryOne( @Param("name") String name,@Param("id")Long id );
List<HashMap<Object, Object>> queryAll( @Param("name") String name );
int add( @Param("name")String name ,@Param("clumus") Object[] clumus, @Param("values") Object ...values );
void update ( @Param("id") Long id, @Param("name") String name, @Param("params")Object []params );
void del(@Param("name")String lowerCase, @Param("id")Long id);
}
Dao 的实现类
- 在service中将参数处理好 然后在此 mapper 中使用动态SQL语句进行操作
- 因为不知道查询的时候返回的是啥子 所以 返回类型是一个 hashmap 接收需要用 List
• <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hututu.xinyong.dao.IBaseDao" >
<!-- 按id查找一个 -->
<select id="queryOne" resultType="hashmap">
select * from ${name} where id=#{id}
</select>
<!-- 查询所有 -->
<select id="queryAll" resultType="hashmap">
select * from ${name}
</select>
<insert id="add" >
insert into ${name}
<foreach collection="clumus" item="clumu" open="(" separator="," close=")" >
${clumu}
</foreach> values
<foreach collection="values" item="value" open="(" separator="," close=")" >
#{value}
</foreach>
</insert>
<update id="update">
update ${name}
<set>
<foreach collection="params" item="param" >
${param},
</foreach>
</set>
where id=#{id}
</update>
<update id="del">
update ${name}
<set>
dr=1
</set>
where id=#{id}
</update>
</mapper>