【mybatis随手记】获取Mapper接口上的泛型

文章来源原创   作者:临窗旋墨   发布时间:2023-10-16   阅读:783   标签:mybatis,springboot 分类:mybatis 专题:解决方案

【mybatis随手记】获取Mapper接口上的泛型

一、背景说明

  1. 项目中的代码通过代码生成器统一生成
  2. mybatis父接口中定义了一些统一的方法,并限定了Model泛型

    1. public interface BaseMapper<T> {
    2. /**
    3. * 查询列表
    4. * @param lookup query condition
    5. * @return list
    6. */
    7. List<T> list(Lookup lookup);
    8. // 其他一些统一的方法 略
    9. }
  3. 在运行时时候,期望通过Model class调用mapper的一些通用方法

  4. 所以需要在运行时候获取Mapper接口上的泛型类型,反向获取到Mapper

实现代码

  1. 通过spring注入全部的BaseMapper的子接口列表
  2. 获取接口上的泛型,放如Map中,key为Model class,value为mapper
  3. 注意事项:
    • 3.1 注入spring中的Mapper,本质上为一个MapperProxy,而不是我们的原始Mapper
    • 3.2 MapperProxy上的泛型<T>才是我们真正的Mapper接口,
    • 3.3 所以需要获取到我们的真实Mapper后,再获取Mapper上的泛型即可。
  1. /**
  2. * 描述: 所有mapper的通用查询汇总:可以根据model class 获取对应的mapper,然后调用BaseMapper的通用数据库操作
  3. * @author Vic.xu
  4. * @date 2023-10-16 14:55
  5. */
  6. public class CommonBaseMapperService implements InitializingBean {
  7. private static final Logger LOGGER = LoggerFactory.getLogger(CommonBaseMapperService.class);
  8. /**
  9. * 注入全部的BaseMapper 的子接口
  10. */
  11. @Autowired
  12. private List<BaseMapper<?>> mappers;
  13. private Map<Class<?>, BaseMapper<?>> mapperMap;
  14. @Override
  15. public void afterPropertiesSet() throws Exception {
  16. LOGGER.info("all BaseMapper size is {}", mappers.size());
  17. mapperMap = new HashMap<>();
  18. for (BaseMapper<?> mapper : mappers) {
  19. Class<?> modelGeneric = getModelGenericFromMapper(mapper);
  20. if (mapperMap.containsKey(modelGeneric)) {
  21. LOGGER.warn("习总中包含关于{}对象的BaseMapper超过一个,请注意检查", modelGeneric.getName());
  22. continue;
  23. }
  24. mapperMap.putIfAbsent(modelGeneric, mapper);
  25. }
  26. LOGGER.info("all BaseMapper no duplicate size is {}", mapperMap.size());
  27. }
  28. /**
  29. * 通过mapper获取mapper上的model泛型
  30. * @param mapper spring里注入的mapper,实际上为 MapperProxy,需要通过它获取到真实的mapper接口类,然后获取mapper上的泛型
  31. * @see MapperProxy
  32. * @return model generic
  33. */
  34. private Class<?> getModelGenericFromMapper(BaseMapper<?> mapper) {
  35. Type[] genericInterfaces = mapper.getClass().getGenericInterfaces();
  36. //MapperProxy 上的泛型记为mapper 接口类型
  37. Class<?> realMapperClass = (Class<?>) genericInterfaces[0];
  38. Type[] types = realMapperClass.getGenericInterfaces();
  39. ParameterizedType parameterizedType = (ParameterizedType) types[0];
  40. Type type = parameterizedType.getActualTypeArguments()[0];
  41. return (Class<?>) type;
  42. }
  43. @SuppressWarnings("unchecked")
  44. public <T> BaseMapper<T> getMapper(Class<T> modelClass) {
  45. if (!mapperMap.containsKey(modelClass)) {
  46. throw new CommonException("系统中不存在" + modelClass.getName() + "对象队形的Mapper!");
  47. }
  48. return (BaseMapper<T>) mapperMap.get(modelClass);
  49. }
  50. /* ****************** 重写BaseMapper中的相关方法***************************************/
  51. /**
  52. * 查询列表
  53. * @param lookup query condition
  54. * @return list
  55. */
  56. public <T> List<T> list(Lookup lookup, Class<T> modelClass) {
  57. return getMapper(modelClass).list(lookup);
  58. }
  59. // 其他方法略
  60. }

代码较为简单,参见gitee.


发表评论

目录