远方的灯塔 - 专注于服务端技术分享 远方的灯塔 - 专注于服务端技术分享
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)

Terwer Green

一个后端老菜鸟
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)
  • JavaSE

  • 开源框架

    • MyBatis

      • JDBC的问题分析
      • 自定义持久层框架的设计思路
      • 自定义持久层框架的代码实现一
      • 自定义持久层框架的代码实现二
      • 使用getMapper方式对自定义持久层框架进行优化
        • 问题分析
        • 解决思路
          • getMapper+动态代理方式优化
        • 优化版代码
        • 默认实现方式
      • MyBatis的基本介绍及优势
      • MyBatis的基本使用
      • Mybatis基本流程及配置文件解析
      • MyBatis复杂映射开发之一对一查询
      • MyBatis复杂映射开发之一对多查询
      • MyBatis复杂映射开发之多对多查询
      • MyBatis常用注解及基本增删改查的注解实现
      • MyBatis的注解实现复杂映射开发
      • MyBatis缓存的概念
      • MyBatis的一级缓存
      • MyBatis的二级缓存
      • MyBatis的二级缓存整合redis
      • MyBatis-RedisCache源码分析
  • Linux

  • Struts2

  • Hibernate

  • Webservice

  • 分布式

  • 分布式框架

  • 后端开发
  • 开源框架
  • MyBatis
terwer
2022-08-29
目录

使用getMapper方式对自定义持久层框架进行优化

# 问题分析

1、Dao层使用持久层框架,存在代码重复,整个操作过程模板重复(加载配置文件、创建SqlSessionFactory、生产SqlSession)

2、存在硬编码(statementId)

# 解决思路

# getMapper+动态代理方式优化

使用代理模式生成Dao层接口的实现类

​

​

SqlSession接口新增getMapper方法

    fun <T> getMapper(mapperClass: Class<*>?): T
    
    1
    public <T> T getMapper(Class<?> mapperClass);
    
    1
    // Make sure to add code blocks to your code group

    DefaultSqlSession中getMapper方法的实现

      override fun <T> getMapper(mapperClass: Class<*>): T {
          // 使用JDK动态代理为Dao接口生成代理对象
          return Proxy.newProxyInstance(
              DefaultSqlSession::class.java.classLoader,
              arrayOf(mapperClass)
          ) { proxy, method, args -> // 底层还是执行JDBC
              // 准备参数1
              // statemendid=namespace.id,获取不到
              // statemendid=接口全限定名.方法名
              val clazzName = method.declaringClass.name
              val methodName = method.name
              val statementId = "$clazzName.$methodName"
      
              // 准备参数2:params=args
      
              // 获取被调用方法的返回类型
              val genericReturnType = method.genericReturnType
              // 判断是否进行了泛型类型参数化
              if (genericReturnType is ParameterizedType) {
                  selectList<Any>(statementId, *args)
              } else selectOne<Any>(statementId, *args)
          } as T
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      @Override
      public <T> T getMapper(Class<?> mapperClass) {
          // 使用JDK动态代理为Dao接口生成代理对象
          return (T) Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
              @Override
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  // 底层还是执行JDBC
                  // 准备参数1
                  // statemendid=namespace.id,获取不到
                  // statemendid=接口全限定名.方法名
                  String clazzName = method.getDeclaringClass().getName();
                  String methodName = method.getName();
                  String statementId = clazzName + "." + methodName;
      
                  // 准备参数2:params=args
      
                  // 获取被调用方法的返回类型
                  Type genericReturnType = method.getGenericReturnType();
                  // 判断是否进行了泛型类型参数化
                  if (genericReturnType instanceof ParameterizedType) {
                      return selectList(statementId, args);
                  }
      
                  return selectOne(statementId, args);
              }
          });
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      // Make sure to add code blocks to your code group

      # 优化版代码

      mybatis-proxy/custom-persistence (opens new window)

      # 默认实现方式

      mybatis-normal/custom-persistence (opens new window)

      文章更新历史

      2022/05/08 feat:增加Kotlin实现。

      编辑 (opens new window)
      #custom#dao#persistence#framework#mybatis#mybatis-5#mapper
      上次更新: 2023/02/22, 13:47:25
      自定义持久层框架的代码实现二
      MyBatis的基本介绍及优势

      ← 自定义持久层框架的代码实现二 MyBatis的基本介绍及优势→

      最近更新
      01
      解决css部分border被圆角切掉之后圆角的边框消失问题
      03-18
      02
      使用TypeScript开发一个自定义的Node-js前端开发脚手架
      03-08
      03
      Github-Actions使用release-please实现自动发版
      03-06
      更多文章>
      Theme by Vdoing | Copyright © 2011-2023 Terwer Green | MIT License | 粤ICP备2022020721号-1 | 百度统计
      • 跟随系统
      • 浅色模式
      • 深色模式
      • 阅读模式