Mybatis源码学习一

  1.创建Mybatis的相关依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>MyBatisDemo</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <!--添加Spring依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <!--添加Spring-JDBC依赖 -->
        <!--提供了数据库连接池-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>


        <!--添加Mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <!--添加Mybatis-Spring依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- 加入MySQL依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <!--添加日志依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.8.0-beta4</version>
        </dependency>
        <!--添加log4j依赖 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

    </dependencies>
</project>

  2.创建配置类:

 1 package com.wk.app;
 2 
 3 import org.apache.ibatis.logging.log4j.Log4jImpl;
 4 import org.apache.ibatis.session.SqlSessionFactory;
 5 import org.mybatis.spring.SqlSessionFactoryBean;
 6 import org.mybatis.spring.annotation.MapperScan;
 7 import org.springframework.context.annotation.Bean;
 8 import org.springframework.context.annotation.ComponentScan;
 9 import org.springframework.context.annotation.Configuration;
10 import org.springframework.jdbc.datasource.DriverManagerDataSource;
11 
12 import javax.sql.DataSource;
13 
14 /**
15  * 配置类
16  */
17 @Configuration
18 @ComponentScan("com.wk")
19 @MapperScan("com.wk.dao")//作用是扫描添加了@Mapper注解的类
20 public class APPConfig {
21 
22     /**
23      * 创建数据源
24      * @return
25      */
26     @Bean
27     public DataSource dataSource(){
28         DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
29         driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
30         driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC");
31         driverManagerDataSource.setUsername("root");
32         driverManagerDataSource.setPassword("root");
33         return driverManagerDataSource;
34     }
35 
36     /**
37      * 创建SqlSessionFactoryBean实例
38      * @return
39      * @throws Exception
40      */
41     @Bean
42     public SqlSessionFactory sqlSessionFactory() throws Exception {
43         SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
44         factoryBean.setDataSource(dataSource());
45         //通过编码方式设置mybatis的配置
46         /*org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
47         configuration.setLogImpl(Log4jImpl.class);
48         factoryBean.setConfiguration(configuration);*/
49         return factoryBean.getObject();
50     }
51 }

  3.创建Mapper接口,并实现查询语句:

 1 package com.wk.dao;
 2 
 3 import com.wk.entity.Seckill;
 4 import org.apache.ibatis.annotations.Param;
 5 import org.apache.ibatis.annotations.Select;
 6 
 7 import java.math.BigInteger;
 8 
 9 public interface SeckillMapper {
10 
11     @Select("SELECT * FROM seckill WHERE seckill_id = #{seckillId}")
12     Seckill querySeckillById(@Param("seckillId") BigInteger seckillId);
13 }

  4.创建service注入Mapper依赖:

 1 @Service("seckillService")
 2 public class SeckillServiceImpl implements SeckillService {
 3     //注入依赖
 4     @Autowired
 5     SeckillMapper seckillMapper;
 6 
 7     public Seckill getSeckillById(BigInteger seckillId) {
 8         return seckillMapper.querySeckillById(seckillId);
 9     }
10 }

  5.创建测试类:

 1 /**
 2  * 测试类
 3  */
 4 public class Test {
 5     public static void main(String[] args) {
 6         //org.apache.ibatis.logging.LogFactory.useLog4JLogging();
 7         ApplicationContext context = new AnnotationConfigApplicationContext(APPConfig.class);
 8         SeckillService service = (SeckillService) context.getBean("seckillService");
 9         System.out.println(service.getSeckillById(new BigInteger("1000")));
10     }
11 }

  到这里,一个完整的mybatis功能就完成了。

  mybatis实现sql语句日志打印的方式(有两种):

  第一种:

    1.创建log4j.properties,参考mybatis官网

1 # Global logging configuration
2 log4j.rootLogger=DEBUG,stdout
3 # MyBatis logging configuration...设置sql语句的打印作用域
4 #log4j.logger.org.mybatis.example.BlogMapper=TRACE
5 log4j.logger.com.wk.dao.SeckillMapper.querySeckillById=TRACE
6 # Console output...
7 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
8 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
9 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

    2.引入log4j的依赖:

<!-- 引入log4j的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

  3.在test类中加入执行方法org.apache.ibatis.logging.LogFactory.useLog4JLogging();:

 1 /**
 2  * 测试类
 3  */
 4 public class Test {
 5     public static void main(String[] args) {
 6         //日志打印sql执行语句
 7         org.apache.ibatis.logging.LogFactory.useLog4JLogging();
 8         ApplicationContext context = new AnnotationConfigApplicationContext(APPConfig.class);
 9         SeckillService service = (SeckillService) context.getBean("seckillService");
10         System.out.println(service.getSeckillById(new BigInteger("1000")));
11     }
12 }

  第二种:

    通过编码的方式,来对程序进行控制,添加日志打印功能

    使用Configuration 类的setLogImpl(Log4jImpl.class);方法进行功能实现。

 1 /**
 2  * 配置类
 3  */
 4 @Configuration
 5 @ComponentScan("com.wk")
 6 @MapperScan("com.wk.dao")//作用是扫描添加了@Mapper注解的类
 7 public class APPConfig {
 8 
 9     /**
10      * 创建数据源
11      * @return
12      */
13     @Bean
14     public DataSource dataSource(){
15         DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
16         driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
17         driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC");
18         driverManagerDataSource.setUsername("root");
19         driverManagerDataSource.setPassword("root");
20         return driverManagerDataSource;
21     }
22 
23     /**
24      * 创建SqlSessionFactoryBean实例
25      * @return
26      * @throws Exception
27      */
28     @Bean
29     public SqlSessionFactory sqlSessionFactory() throws Exception {
30         SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
31         factoryBean.setDataSource(dataSource());
32         //通过编码方式设置mybatis的配置
33         org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
34         configuration.setLogImpl(Log4jImpl.class);
35         factoryBean.setConfiguration(configuration);
36         return factoryBean.getObject();
37     }
38 }

 Mybatis在于spring整合之后,一级缓存失效的原因是什么?

  因为mybatis和spring整合之后,spring就会管理mybatis用于数据库查询的sqlSession,spring对这个sqlSession进行扩展,使用一个sqlSessionTemplate类做了一个代理,这个类在spring容器启动的时候注入给了Mapper,这个类代替了原来Mybatis包中自己的DefaultSqlSession类,所以这个sqlSession就在这个代理对象中了,每次查询完之后,spring就会通过这个代理对象来关闭sqlSession,所以即便是相同的查询语句,mybatis每次都要使用新的sqlSession建立连接进行查询,查询完之后,这个sqlSession就被spring容器关闭了,所以导致mybatis的一级缓存失效。

Mybatis的二级缓存的缺点:

  Mybatis的二级缓存是基于命名空间的,也就是说,只有在一个Mapper类下的方法,如果一个查询方法和一个更新方法不在同一个Mapper类下进行的,那么mybatis的二级缓存就会忽视更新之后的数据,仍然使用之前的缓存,导致数据错误。

posted @ 2020-04-03 20:52  WK_BlogYard  阅读(173)  评论(0编辑  收藏  举报