MyBatis通过泛型实现对Service和Mapper类简单封装

参考链接:https://www.yuque.com/page/luan.ma/ssm-baseservice
更新:

  • 2020/04/27
    在前几天的实际使用中进一步抽象出BaseService接口,定义了Service类该有的方法
    修改了泛型的继承关系,在Service具体实现类中调用Mapper具体接口中自定义方法时,不再需要先获取mapper,直接调用即可

主要是通过泛型自动注入对应的Mapper接口和返回类型
如需添加自定义方法,需要在Mapper具体接口中定义,和在Service具体实现类中调用

结构图
MyBatis通过泛型实现对Service和Mapper类简单封装_第1张图片

以下泛型M均为Mapper接口,泛型E均为实体类

BaseMapper接口定义了基础的增删改查方法

public interface BaseMapper<E> {
    E get(int id);
    int add(E obj);
    int update(E obj);
    int delete(E obj);
}

Service4Dao接口定义了设置和获取Mapper的方法

public interface Service4Dao<M> {
    M setMapper();
    M getMapper();
}

Service4DaoImpl类实现了Service4Dao和InitializingBean接口,注入了SqlSession
通过反射获取泛型M的具体类型,再通过SqlSession获取mapper

public class Service4DaoImpl<M> implements Service4Dao<M>, InitializingBean {
    protected M mapper;
    @Autowired
    protected SqlSession sqlSession;

    @Override
    public M setMapper() {
        Class clz= (Class) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return (M) sqlSession.getMapper(clz);
    }
    @Override
    public M getMapper() {
        return mapper;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        mapper = setMapper();
    }
}

BaseServer接口定义了Service类基础的增删改查方法

public interface BaseServer<E> {
    E get(int id);
    int add(E obj);
    int update(E obj);
    int delete(E obj);
}

抽象类BaseServiceImpl类型继承Service4DaoImpl类,拥有了自动注入Mapper接口的方法
实现了BaseService接口,约束了基础的增删改查方法,并实现了对应的方法,调用对应的BaseMapper接口的方法
并且继承了各自的泛型,约束了泛型M为BaseMapper接口的子接口,泛型的具体类型留给子类定义

public abstract class BaseServiceImpl<M extends BaseMapper,E> extends Service4DaoImpl<M> implements BaseServer<E> {
    public E get(int id){
        return (E) mapper.get(id);
    }
    public int add(E obj){
        return  mapper.add(obj);
    }
    public int update(E obj){
        return  mapper.update(obj);
    }
    public int delete(E obj) {
        return mapper.delete(obj);
    }
}

使用:
Mapper具体接口继承BaseMapper接口,在xml文件中编写对应的SQL语句
如需增加方法只管加上就行
不需要BaseMapper接口的某些方法,可对该方法添加default关键字进行覆盖和默认实现,返回null或者0等等,无需在xml文件里编写SQL语句,也不会调用

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
    Student get2(int ID); // 自定义方法
    
    @Override
    default int add(Student obj) { // 默认实现,对该方法进行禁用
        return 0;
    }
}

Service具体实现类继承BaseServiceImpl抽象类
在此阶段定义泛型的具体类型,第一个为Mapper具体接口,第二个为该Mapper返回的实体类型
如需增加方法只管加上就行
也可对已实现的方法进行覆盖或重载

@Service
public class TestService extends BaseServiceImpl<StudentMapper, Student> {
    // 覆盖
	public Student get(int ID){
        System.out.println(ID);
        return mapper.get(ID);
    }
    // 重载
    public Student get(int ID,int h) {
        System.out.println(ID+" "+h);
        return mapper.get(ID);
    }
    // 自定义
    public Student get2(int ID){
        System.out.println(ID);
        return mapper.get2(ID); // 调用Mapper接口自定义方法
    }
}

测试

	// 注入 service
	@Autowired
    private TestService service;
    // Service调用对应的方法即可
    Student s1 = service.get(ID); // 方法已覆盖
    Student s2 = service.get(ID,123); // 方法已重载
    Student s3 = service.get2(ID); // TestService类的自定义方法,且调用StudentMapper接口的自定义方法

你可能感兴趣的:(笔记)