编程式使用案例
大部分时候,我们都是在 Spring 里面去集成 MyBatis。因为 Spring 对 MyBatis 的一些操作进行的封装,我们不能直接看到它的本质,所以先看下不使用容器的时候,也就是编程的方式,MyBatis 怎么使用。
1.引入jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
2.创建一个全局配置文件,这里面是对 MyBatis 的核心行为的控制,比如mybatis-config.xml。
<configuration>
<properties resource="db.properties" />
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 控制全局缓存(二级缓存)-->
<setting name="cacheEnabled" value="true"/>
<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
<!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
<!--
<setting name="localCacheScope" value="STATEMENT"/>
-->
<setting name="localCacheScope" value="SESSION"/>
</settings>
<plugins>
<plugin interceptor="com.interceptor.OceanLiPageInterceptor" />
<plugin interceptor="com.interceptor.OceanLiSqlInterceptor"/>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="BlogMapper.xml"/>
<mapper resource="BlogMapperExt.xml"/>
</mappers>
</configuration>
3.添加映射文件Mapper.xml
我们要执行对数据库的操作,必须创建一个会话,这个在MyBatis 里面就是 SqlSession。SqlSession 又是工厂类根据全局配置文件创建的。所以整个的流程就是这样的(如下代码)。最后我们通过 SqlSession 接口上的方法,传入我们的 Statement ID 来执行 SQL。这是第一种方式。这种方式有一个明显的缺点,就是会对 Statement ID 硬编码,而且不能在编译时进行类型检查,所以通常我们会使用第二种方式,就是定义一个 Mapper 接口的方式。这个接口全路径必须跟 Mapper.xml 里面的namespace 对应起来,方法也要跟 StatementID 一一对应。
public void testMapper() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream (resource);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlogById(1);
System.out.println(blog);
} finally {
session.close();
}
}
核心对象的生命周期
1)SqlSessionFactoryBuilder
它是用来构建SqlSessionFactory的 , 而SqlSessionFactory 只需要一个,所以只要构建了这一个 SqlSessionFactory,它的使命就完成了,也就没有存在的意义了。所以它的生命周期只存在于方法的局部。
2)SqlSessionFactory
SqlSessionFactory 是用来创建 SqlSession的,每次应用程序访问数据库,都需要创建一个会话。因为我们一直有创建会话的需要,所以 SqlSessionFactory 应该存在于应用的整个生命周期中(作用域是应用作用域)。创建 SqlSession 只需要一个实例来做这件事就行了,否则会产生很多的混乱,和浪费资源。所以我们要采用单例模式。
3)SqlSession
SqlSession 是一个会话,因为它不是线程安全的,不能在线程间共享。所以我们在请求开始的时候创建一个 SqlSession 对象,在请求结束或者说方法执行完毕的时候要及时关闭它(一次请求或者操作中)。
4)Mapper