一、MyBatis日志配置
MyBatis做为一个封装好的ORM框架,其运行过程我们没办法跟踪,为了让开发者了解MyBatis执行流程及每个执行步骤所完成的工作,MyBatis框架本身支持log4j日志框架,对运行的过程进行跟踪记录。我们只需对MyBatis进行相关的日志配置,就可以看到MyBatis运行过程中的日志信息。
- 添加日志框架依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- 添加日志配置文件
- 在resources目录下创建名为
log4j.properties
文件 - 在
log4j.properties
文件配置日志输出的方式
# 声明日志的输出级别及输出方式
log4j.rootLogger=DEBUG,stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 定义日志的打印格式 %t 表示线程名称 %5p 日志级别 %msg日志信息
log4j.appender.stdout.layout.ConversionPattern=[%t] %5p - %msg \:%m%n
- 日志信息的级别
二、MyBatis缓存
MyBatis是基于JDBC的封装,使数据库操作更加便捷;MyBatis除了对JDBC操作步骤进行封装之外也对其性能进行了优化:
- 在MyBatis引入缓存机制,用于提升MyBatis的检索效率
- 在MyBatis引入延迟加载机制,用于减少对数据库不必要的访问
缓存的实现过程
缓存,就是存储数据的内存
1.检查缓存中是否存在要查询的数据
2.如果存在,则直接从缓存中获取数据并返回(不会查询数据库)
3.如果不存在,则从数据库查询,查询之后将数据返回,同时存储到缓存中,以供下次查询使用
MyBatis缓存分为一级缓存和二级缓存
-
一级缓存
一级缓存也叫做SqlSession级缓存,为每个SqlSession单独分配的缓存内存,无需手动开启可直接使用;多个SqlSession的缓存是不共享的。特性:
1.如果多次查询使用的是同一个SqlSession对象,则第一次查询之后数据会存放到缓存,后续的查询则直接访问缓存中存储的数据;2.如果第一次查询完成之后,对查询出的对象进行修改(此修改会影响到缓存),第二次查询会直接访问缓存,造成第二次查询的结果与数据库不一致;
3.当我们进行在查询时想要跳过缓存直接查询数据库,则可以通过sqlSession.clearCache();来清除当前SqlSession的缓存;
4.如果第一次查询之后第二查询之前,使用当前的sqlsession执行了修改操作,此修改操作会使第一次查询并缓存的数据失效,因此第二次查询会再次访问数据库。
测试代码:
@Test
public void testQueryMemberById(){
SqlSession sqlSession1 = MyBatisUtil.getSqlSessionFactory().openSession();
SqlSession sqlSession2 = MyBatisUtil.getSqlSessionFactory().openSession();
MemberDAO memberDAO1 = sqlSession1.getMapper(MemberDAO.class);
Member member1 = memberDAO1.queryMemberById(1);
System.out.println(member1);
member1.setMemberAge(99);
sqlSession1.clearCache();
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
MemberDAO memberDAO2 = sqlSession1.getMapper(MemberDAO.class);
Member member2 =memberDAO2.queryMemberById(1);
System.out.println(member2);
}
两次查询与数据库数据不一致问题
第一次查询之后,进行了修改操作,数据库数据已经被修改,但是第二查询的时候依然显示的修改前的数据。
原因:修改操作和查询操作不是同一个线程,因此使用的不同的studentDAO对象(使用不同的sqlSession),因此修改操作不会导致查询操作的缓存失效,第二次查询的时候依然访问的是缓存而没有查数据库
解决方案:
1.让修改操作和查询操作使用相同的SqlSession(不太合理)
2.每次进行查询操作之后,清空缓存,让再次查询的时候绕过缓存直接访问数据库
-
二级缓存
二级缓存也称为SqlSessionFactory级缓存,通过同一个factory对象获取的Sqlsession可以共享二级缓存;在应用服务器中SqlSessionFactory是单例的,因此我们二级缓存可以实现全局共享。特性:
1.二级缓存默认没有开启,需要在mybatis-config.xml中的settings标签开启
2.二级缓存只能缓存实现序列化接口的对象
在mybatis-config.xml开启使用二级缓存
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在需要使用二级缓存的Mapper文件中配置cache标签使用功能二级缓存
<cache/>
被缓存的实体类实现序列化接口
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member implements Serializable {
private int memberId;
private String memberNick;
private String memberGender;
private int memberAge;
private String memberCity;
}
查询操作的缓存开关
<select id="queryMemberById" resultMap="memberMap" useCache="false">
select member_id,member_nick,member_gender,member_age,member_city
from members
where member_id=#{mid}
</select>
三、延迟加载
延迟加载也叫懒加载、惰性加载,使用延迟加载可以提高程序的运行效率,针对于数据持久层的操作,在某些特定的情况下去访问特定的数据库,在其他情况下可以不访问某些表,从一定程度上减少了Java应用与数据库的交互次数。
如果在MyBatis开启了延迟加载,在执行了子查询(至少查询两次及以上)时,默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需使用子查询结果,则子查询不会执行.
开启延迟加载:
config.xml中
<settings>
<!--打印SQL-->
<setting namem"logImpl" valuem"STDOUT_LOGGING-/><!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true" />
</settings>
mapper层中:fetchType=“lazy”
<resultMap id="classMap" type="Clazz">
<id column="cid" property="classId"/>
<result column="cname" property="className"/>
<result column="cdesc" property="classDesc"/>
<collection property="stus" select="com.qfedu.dao.StudentDAO.queryStudentsByCid" column="cid" fetchType="lazy"/>
</resultMap>
<select id="queryClassByCid" resultMap="classMap">
select cid,cname,cdesc
from classes
where cid=#{cid}
</select>
四、Mybatis逆向工程
逆向工程即传统开发的反向工程
Mybatis框架需要:实体类、自定义Mapper接口,Mapper.xml
传统的开发中上述的三个组件需要开发者手动创建,逆向工程可以帮助开发者来自动创建三个组件,减轻开发者的工作量,提高工作效率。
使用方法
MyBatis Generator,简称MBG,是一个专门为MyBatis框架开发者定制的代码生成器,可自动生成MyBatis 框架所需的实体类、Mapper 接口、Mapper .xml,支持基本的CRUD操作,但是一些相对复杂的SQL需要开发者自己来完成。
1.新建Maven工程,pom.xml文件中引入相关依赖
2.创建MBG配置文件generatorConfig.xml
1)jdbcConnection配置数据库连接信息
2)javaModelGenerator配置JavaBean 的生成策略。
3)sqlMapGenerator配置SQL映射文件生成策略。
4)JavaClientGenerator配置 Mapper接口的生成策略。
5)table配置目标数据表。(tableName:表名,domainObjectName: JavaBean类名)
3.创建generator执行的类
执行完后会自动创建entity类等