源码解读: https://www.cnblogs.com/zhjh256/p/8512392.html

mybatis

springboot装配mybatis流程 ==待补充

概念

1:什么是mybatis

一种半ROM框架,实现数据库对象到java对象的转换,内部封装了jdbc链接,获取statement等操作,让程序员专注业务本身

基础

spring集成mybatis

直接用插件生成相关文件

  1. <plugin>
  2. <groupId>org.mybatis.generator</groupId>
  3. <artifactId>mybatis-generator-maven-plugin</artifactId>
  4. <version>1.3.5</version>
  5. <configuration>
  6. <!-- 配置文件 路径 -->
  7. <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
  8. <verbose>true</verbose>
  9. <overwrite>true</overwrite>
  10. </configuration>
  11. <executions>
  12. <execution>
  13. <phase>deploy</phase>
  14. <id>Generate MyBatis Artifacts</id>
  15. <goals>
  16. <goal>generate</goal>
  17. </goals>
  18. </execution>
  19. </executions>
  20. <dependencies>
  21. <dependency>
  22. <groupId>org.mybatis.generator</groupId>
  23. <artifactId>mybatis-generator-core</artifactId>
  24. <version>1.3.5</version>
  25. </dependency>
  26. </dependencies>
  27. </plugin>

配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE generatorConfiguration
  3. PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  4. "http://mybatis.org/dtd/mybatis-generator -config_1_0.dtd">
  5. <generatorConfiguration>
  6. <!--classPathEntry:数据库的JDBC驱动,换成你自己的驱动位置 -->
  7. <classPathEntry location="/Users/luyinbin/.m2/repository/mysql/mysql-connector-java/5.1.47/mysql-connector-java-5.1.47.jar" />
  8. <!-- 一个数据库一个context -->
  9. <!--defaultModelType="flat" 大数据字段,不分表 -->
  10. <context id="MysqlTables" targetRuntime="MyBatis3" defaultModelType="flat">
  11. <property name="autoDelimitKeywords" value="true"/>
  12. <property name="beginningDelimiter" value="`"/>
  13. <property name="endingDelimiter" value="`"/>
  14. <property name="javaFileEncoding" value="utf-8"/>
  15. <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
  16. <plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
  17. <!-- 注释 -->
  18. <commentGenerator>
  19. <property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
  20. <property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳-->
  21. </commentGenerator>
  22. <!-- jdbc连接 -->
  23. <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/company_frame" userId="root"
  24. password="12345678"/>
  25. <!-- 类型转换 -->
  26. <javaTypeResolver>
  27. <!-- 是否使用bigDecimal false可自动转化以下类型(Long, Integer, Short, etc.) -->
  28. <property name="forceBigDecimals" value="false"/>
  29. </javaTypeResolver>
  30. <!-- 生成实体类地址 -->
  31. <javaModelGenerator targetPackage="com.firstexample.lesson.entity" targetProject="src/main/java">
  32. <property name="enableSubPackages" value="false"/>
  33. <property name="trimStrings" value="true"/>
  34. </javaModelGenerator>
  35. <!-- 生成mapxml文件 -->
  36. <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
  37. <property name="enableSubPackages" value="false"/>
  38. </sqlMapGenerator>
  39. <!-- 生成mapxml对应client,也就是接口dao -->
  40. <javaClientGenerator targetPackage="com.firstexample.lesson.mapper" targetProject="src/main/java" type="XMLMAPPER">
  41. <property name="enableSubPackages" value="false"/>
  42. </javaClientGenerator>
  43. <!-- <table tableName="sys_user" domainObjectName="SysUser"
  44. enableCountByExample="false"
  45. enableUpdateByExample="false"
  46. enableDeleteByExample="false"
  47. enableSelectByExample="false"
  48. selectByExampleQueryId="true">
  49. <columnOverride column="sex" javaType="java.lang.Integer"/>
  50. <columnOverride column="status" javaType="java.lang.Integer"/>
  51. <columnOverride column="create_where" javaType="java.lang.Integer"/>
  52. <columnOverride column="deleted" javaType="java.lang.Integer"/>
  53. </table>-->
  54. <table tableName="sys_dept" domainObjectName="SysDept"
  55. enableCountByExample="false"
  56. enableUpdateByExample="false"
  57. enableDeleteByExample="false"
  58. enableSelectByExample="false"
  59. selectByExampleQueryId="true">
  60. <columnOverride column="status" javaType="java.lang.Integer"/>
  61. <columnOverride column="deleted" javaType="java.lang.Integer"/>
  62. </table>
  63. <table tableName="sys_log" domainObjectName="SysLog"
  64. enableCountByExample="false"
  65. enableUpdateByExample="false"
  66. enableDeleteByExample="false"
  67. enableSelectByExample="false"
  68. selectByExampleQueryId="true">
  69. </table>
  70. <table tableName="sys_permission" domainObjectName="SysPermission"
  71. enableCountByExample="false"
  72. enableUpdateByExample="false"
  73. enableDeleteByExample="false"
  74. enableSelectByExample="false"
  75. selectByExampleQueryId="true">
  76. <columnOverride column="type" javaType="java.lang.Integer"/>
  77. <columnOverride column="status" javaType="java.lang.Integer"/>
  78. <columnOverride column="deleted" javaType="java.lang.Integer"/>
  79. </table>
  80. <table tableName="sys_role" domainObjectName="SysRole"
  81. enableCountByExample="false"
  82. enableUpdateByExample="false"
  83. enableDeleteByExample="false"
  84. enableSelectByExample="false"
  85. selectByExampleQueryId="true">
  86. <columnOverride column="status" javaType="java.lang.Integer"/>
  87. <columnOverride column="deleted" javaType="java.lang.Integer"/>
  88. </table>
  89. <table tableName="sys_role_permission" domainObjectName="SysRolePermission"
  90. enableCountByExample="false"
  91. enableUpdateByExample="false"
  92. enableDeleteByExample="false"
  93. enableSelectByExample="false"
  94. selectByExampleQueryId="true">
  95. </table>
  96. <table tableName="sys_user_role" domainObjectName="SysUserRole"
  97. enableCountByExample="false"
  98. enableUpdateByExample="false"
  99. enableDeleteByExample="false"
  100. enableSelectByExample="false"
  101. selectByExampleQueryId="true">
  102. </table>
  103. <table tableName="sys_user" domainObjectName="SysUser"
  104. enableCountByExample="false"
  105. enableUpdateByExample="false"
  106. enableDeleteByExample="false"
  107. enableSelectByExample="false"
  108. selectByExampleQueryId="true">
  109. </table>
  110. </context>
  111. </generatorConfiguration>

配置好后运行插件,会生成三个文件
1:xxxxmapper.xml 与数据库的交互,写sql的地方
2:xxxmapper.java 与springboot的交互接口 ,注入ioc容器中
3:xxx.java 一般与表名相同,数据库 到 service的实体映射,这个类中字段与表一一对应,也可以自定义~~

注意点:

1:xml中id 与 接口名保持一致
2:返回类型确保正确
3:映射字段修改正确

使用

1:写好sql
2:注入接口
3:调用

  1. @Autowired
  2. private SysLogMapper sysLogMapper;
  3. @GetMapping("/select")
  4. public SysLog select(@RequestParam("id") String id){
  5. List<SysLog> sysLogs = sysLogMapper.selectAll();
  6. SysLog sysLog = sysLogMapper.selectByPrimaryKey(id);
  7. return sysLog;
  8. }

三种实现方式

一:
1:定义接口,定义pojo对象
2:实现接口并集成SqlSessionDaoSupport
3:配置java bean 到 mapper.xml 的映射
4:获取sqlsession对象并执行
二:
接口映射,其实跟上面的一样,内置 MapperFactoryBean 集成了SqlSessionDaoSupport 实现方法getObject()获取到了mapper对象()getSqlSession().getMapper(this.mapperInterface); 根据接口对象获取

问题

1:mapper接口如何跟xml交互,过程
2:mapper接口如何跟业务层交互
主要是 MapperProxy 先从缓存获取方法(cachedInvoker)
如果没有则创建,
再调用public Object execute(SqlSession sqlSession, Object[] args)
最终还是调到sqlsession中的方法执行
这块代码有空再读image.png

核心部件

MybatisAutoConfiguration

spring中的自动装配设置
其中实例化了 SqlSessionFactoryBean 获取 SqlSessionFactory对象 和
SqlSessionTemplate两个关键对象

Configuration

核心数据,里面缓存了基本上需要用到的一切东西

SqlSessionFactory /SqlSessionTemplate

关键类:创建sqlsession

SqlSessionFactoryBuilder

SqlSessionFactory 构造器

statement

里面封装了一些执行sql所需要的信息,比如具体的sql语句

Executor sql执行器

1:simple 每次执行创建一个新statment 并 commit 执行完后close —-默认执行器
2:Reuse 相比于simple。会缓存 statment。sql作为key,存在map
3: Batch 执行updata时 将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:
Executor的这些特点,都严格限制在SqlSession生命周期范围内。

如何指定excutor
设置(settings)可以指定默认的ExecutorType执行器类型
SqlSession openSession(ExecutorType execType)

SqlSessionDaoSupport

获取sqlsession。可以自定义执行,如果不用mybatis接口映射方式,需要继承该类,通过 getSqlSession 拿到sqlsession
内置了MapperFactoryBean 继承该类,初始化是被加载进容器

。。。。待补充

mapper.xml 常用标签

1. if 条件判断

  1. <if test = "条件">
  2. 代码块
  3. </if>

2. where

可以理解为 sql 中的where 只有条件中1个以上生效才会拼接where,如果第一个条件and/or开头,自动处理

3. set

同sql中的set,动态凭借sql语句,可以出去前后不想关符号

  1. trim

类似String中的trim。处理sql语句

  1. <trim prefix="(" prefixOverrides="and" suffie=")">
  2. 参数解释 prefix 前置处理 suffie后置处理 prefixOverrides删除前置符 suffieOverrides 删除后置符

5. choose when otherwise

类似java switch case 或者 if/else 由于mybatis不支持ifelse。可以用这代替 when 里带条件

  1. <choose>
  2. <when test="cxxx">
  3. and ${xxxx}
  4. </when>
  5. <otherwise>
  6. xxx
  7. </otherwise>
  8. </choose>

6. foreach

  1. <foreach item="item" collection="list" index="index" open="" close="" separator=";">
  2. ## item 迭代别名
  3. collection 迭代数组类型
  4. index 如果为map时代表 key item代表value 数组则代表下标
  5. open 开始标识
  6. separator 分割符
  7. close 结束
  8. </foreach>
  9. 可以理解为groovy eachwithindex 吧所有结果放到 open close 中,以 separator分割

7. bind

绑定变量供上下文使用, 实现类似concat函数功能 比如进行模糊查询的参数拼接

  1. <bind name="hah" value="'%' + id+'%' "></bind>
  2. select * from sys_log where id like #{hah}
  3. 属性解释
  4. name 理解为变量 value 理解为值

8. sql

复用代码段 标签导入

9. parameterType 入参类型

10.parametermao map形式入参

11. resultMap map形式出参

12. resultType 出参映射类型

13. selectKey 一般配合insert语句使用,作为返回值

分页

1:用limit

  1. @GetMapping("/selectAll")
  2. public List<SysLog> selectAll(@RequestParam("page") int page,@RequestParam("pagesize") int pagesize){
  3. int startPage = (page-1) *pagesize;
  4. BaseQuery baseQuery = new BaseQuery(startPage, pagesize);
  5. return sysLogMapper.selectAll(baseQuery);
  6. }
  7. select
  8. <include refid="Base_Column_List"></include>
  9. from
  10. sys_log
  11. limit #{curreyPage},#{pageSize}

2:插件 pagehelper

  1. 依赖
  2. <dependency>
  3. <groupId>com.github.pagehelper</groupId>
  4. <artifactId>pagehelper-spring-boot-starter</artifactId>
  5. <version>1.2.5</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.github.jsqlparser</groupId>
  9. <artifactId>jsqlparser</artifactId>
  10. <version>1.0</version>
  11. </dependency>
  12. service
  13. PageHelper.startPage(page,pagesize);
  14. List<SysLog> sysLogs = sysLogMapper.selectAll(); //紧跟着上面一条,如果有多条只有第一条有效
  15. PageInfo<SysLog> sysLogPageInfo = new PageInfo<>(sysLogs); //封装详细数据,可以不写
  16. return sysLogPageInfo;

todo原理??暂时跟到这儿,有时间再看 ,
大概是 org.apache.ibatis.plugin.Interceptor 提供接口,支持插件
pagehelp实现该接口
QueryInterceptor.plugin 调用 Plugin._wrap 把自身传入_Plugin
org.apache.ibatis.plugin.Plugin 实现了InvocationHandler invoke 调用QueryInterceptor 最终调用到QueryInterceptor.intercept
image.png

自定义数据源

遗留问题

1:spring 自动装配如何注入sqlsession https://blog.csdn.net/zxysshgood/article/details/113701377