目录:从使用开始,一些常用功能,梳理一下代码调用流程,整理一些功能的实现,值得学习参考的地方,最后对于框架中不理解的地方提出的疑问
资源:https://download.csdn.net/download/u013523089/10781601
欢迎大家在评论中指出错误,有什么问题也可以共同交流共同学习,感谢!
网配置教程:
http://www.mybatis.org/mybatis-3/
源码下载:
ORM(来自baidu):
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换
自我梳理了一下mybatis,欢迎大神批评指正,交流学习,感谢!
常用使用说明
- 使用mybatis集成pom配置
使用我的练习项目;第一次自己搭maven
可以在一个maven工程里放子工程,这个方式还挺好的;两个子项目可以共用父项目的pom配置
<dependencies>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!-- mybatis会用到 start -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.21.0-GA</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>2.7.3</version>
</dependency>
<!-- mybatis会用到 end -->
<!-- mybatis 分页插件 -->
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.7</version>
</dependency>
</dependencies>
maven工程配置,pom文件配置;如果需要jar包可以在这里搜
https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api/5.3.1
- 使用generator插件使用
pom配置
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!--允许移动生成的文件-->
<verbose>true</verbose>
<!--允许覆盖生成的文件-->
<overwrite>true</overwrite>
<configurationFile>src/main/resources/config/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>
generator.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 注意这个插件是增量向文件中添加,会重复 -->
<generatorConfiguration>
<!-- 引入配置文件
<properties resource="jdbc.properties"/> -->
<!--数据库驱动路径-->
<classPathEntry location="D:\TSBrowserDownloads\maven\mavenSource\mysql\mysql-connector-java\8.0.13\mysql-connector-java-8.0.13.jar" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
<property name="suppressDate" value="true" /> <!-- 是否生成注释代时间戳-->
</commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/zhaowd?serverTimezone=GMT"
userId="root" password="12345">
</jdbcConnection>
<!-- 类型转换 -->
<javaTypeResolver>
<!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成实体类的包名和位置 注意targetProject的值为实体类放在工程中具体位置的相对路径,-->
<javaModelGenerator targetPackage="zhaowd.source" targetProject="src/main/java">
<!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
<property name="enableSubPackages" value="true"/>
<!-- 是否针对string类型的字段在set的时候进行trim调用 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--XML映射文件,生成的位置(目标包),源代码文件夹-->
<sqlMapGenerator targetPackage="sqlmap" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--XML对应的Mapper类-->
<javaClientGenerator type="XMLMAPPER" targetPackage="zhaowd.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--下面是数据库表名和项目中需要生成类的名称,建议和数据库保持一致,如果有多个表,添加多个节点即可 enable*ByExample
是否生成 example类-->
<table schema="zhaowd" tableName="user_info" domainObjectName="UserInfo" enableCountByExample="false" enableSelectByExample="true" enableUpdateByExample="false" enableDeleteByExample="false">
</table>
</context>
</generatorConfiguration>
使用方法:右键项目–>run as–>maven Build
自动生成mybatis需要的内容,mapper接口,mapper.xml,表实体
默认直接覆盖原有的,所以尽量不要在生成的文件中编写自己的代码,使用单独的文件,防止覆盖
- 分页
mybatis自带方法里的分页参数是对结果集进行分页的,就是假分页
方法1:就是使用sql语句的拼装去分页,直接使用数据库的sql
方法2:使用分页插件,比如pagehelper- pom配置见上面mybatis的配置
- 使用说明:再查询之前增加PageHelper.startPage(当前页,限制数量);即可
- 注意事项见图片代码注释
使用过程中的异常
- Caused by: java.lang.IllegalStateException: Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.
Caused by: java.lang.IllegalStateException: Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.
at org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory.<init>(JavassistProxyFactory.java:55)
at org.apache.ibatis.session.Configuration.<init>(Configuration.java:131)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.<init>(XMLConfigBuilder.java:86)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.<init>(XMLConfigBuilder.java:82)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:77)
... 25 more
Caused by: java.lang.ClassNotFoundException: Cannot find class: javassist.util.proxy.ProxyFactory
缺少jar依赖
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.21.0-GA</version>
</dependency>
- Caused by: java.lang.RuntimeException: MemberAccess implementation must be provided!
ognl版本不对,可能太高了
修改成:
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>2.7.3</version>
</dependency>
源码分析
程序调用链条如下图所示:
1.流程调用图(简化版)
2.复杂点的(这有点乱,结合简化版的看)
- 目录结构说明
annotations:注解定义
binding:绑定mapper接口与mapper.xml的关系
builder:注解+配置解析
cache:缓存
cursor:
datasource:数据源
exceptions:异常
executor:sql的实际执行者
io:读文件
jdbc:底层相关
lang:
logging:日志
mappering:映射到实体
parsing:解析配置+注解
plugin:插件,拦截器
reflection:反射
scripting:参数处理
session:session
transaction:
type:类型
源码
源码的调用流程见上图
学习:
- Configuration
目前mybatis支持两种方式的实现功能- 编程式:只是单纯的使用mybaits去作为持久化层去使用,mybatis提供xml的形式去简化配置
- 集成式:比如集成在spring中使用,可以使用Configuration去设置配置参数
编程式在使用过程中,也会将xml映射到Configuration上
Configuration与SqlSessionFactory一一对应
- 缓存
-
一级缓存:默认开启,session级别的,第一查询进行缓存,第二次查询从缓存里取
- 如果同一个sesssion,在两次查询之间有更新数据的操作(update,delete)并提交,session的所有缓存都会清
- 如果有不同的session,在两次查询之间有更新数据的操作(update,delete),第二次查询的数据就是脏数据了,session之间缓存都是独立的
一级缓存是在取二级缓存之后(如果二级开关开启的话)
设置一级缓存的时候会使用一个占位符去占位,作用:比如在联合查询中,第二个sql在执行时,可能会命中第二个sql在单独执行时的一级缓存,如果获取到缓存的值是这个占位符,表示这个缓存不能使用;应该就是这个联合查询的第二个sql不加载到缓存里,由正在处理的加
-
二级缓存:默认关闭,一般使用第三方实现(redies),nameSpace级别的,共享给所有的sqlSession
- 同一个namespace下的upd,del会清掉该space下的缓存同一个namespace下的upd,del会清掉该space下的缓存
- 如果是关联查询,缓存也只是当前namespace下的;如果另外一个namespace对数据有更新,不会影响其他namespace下的缓存,哪怕是关联查询的第二条sql
-
-
plugin机制 拦截
- InterceptorChain.pluginAll方法,拦截器的开始;拦截的内容就是下图中的类,所有类的创建都会调用这个方法
- 拦截器的过程
- 如果有多个plugin,pluginAll里会循环的去做代理;即已经被代理的实例,可以再被代理;代理先走最外层的
重复代理示例:
- 初始状态
- 第一次被代理
- 第二次被代理
- InterceptorChain.pluginAll方法,拦截器的开始;拦截的内容就是下图中的类,所有类的创建都会调用这个方法
-
ObjectFactory 创建结果对象的实例
- 拿到结果集,创建结果映射对象,就是实体对象(通过反射调用无参构造,如有自定义objectFactory,调用create创建)之后;这个时候还没有映射
- 入参设置同理
-
laze Loading机制
*
- 如果lazyLoading开启,默认是javassist,可选cglib/自定义;会通过config去创建一个proxyFactory(java、cglib)的代理的代理对象
位置:org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(ResultSetWrapper, ResultMap, ResultLoaderMap, String) - 在使用这个对象做get的时候,会调用invoke、intercept方法懒加载查询内容
扩展反射知识:https://blog.csdn.net/u013523089/article/details/83959984
- 如果lazyLoading开启,默认是javassist,可选cglib/自定义;会通过config去创建一个proxyFactory(java、cglib)的代理的代理对象
-
异常机制
使用一个ThreadLocal LOCAL去存每个线程的异常信息,如果有异常输出,这个会打印出每个设置的调用步骤的信息
-
log日志:以log4j2为例
-
连接池:自己做连接池的时候可以有个参考
-
事务
sqlsession–>executor–>transaction{jdbc(使用jdbc的事务,connection),manager(不处理事务,用于集成,由spring管理),自定义}
问题:
- 这个连接超时的含义是什么? sql执行时间过长的限制? 连接超时被断开?
后者的可能性好像大些