Mybatis架构
??Mybatis是持久层的框架,所谓持久层框架就是与数据库交互的框架。之前没有持久层框架的时候,前辈们使用的JDBC来连接数据库,连接数据库的对象是Connection,而在Mybatis也存在一个与数据库交互的对象SqlSession。实际Mybatis在做的一件事就是创建SQLSession。接下来我们看下一个SqlSession生成的流程即Mybatis架构图。 ?
??先对图中涉及到的类做个简单介绍,后面会详细解释:
- SqlMapConfig.xml&&mapper.xml:这是Mybatis的全局配置文件,配置了Mybatis的运行环境等信息。mapper.xml文件是sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载才可被调用。
- SqlSessionFactory:创建SqlSession的工厂类,上面的全局配置文件与映射文件可以理解为原材料,通过SQLSessionFactoryBuilder类来获取。
- SqlSession:由会话工厂(SqlSessionFactory)获取,用于操作数据库的对象。
- Executor:Mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。开发中我们用的是SqlSession,并不会用到该接口的实现类。
- statement:JDBC还没忘的应该对这个很熟悉,Statement是Mybatis一个底层封装对象,它包装了Mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Statement对象,sql的id即是statement的id。
Mybatis入门
导入依赖
普通项目导jar包,Maven项目引入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
从XML构建SqlSessionFactory
Mybatis为我们提供了两种获取SqlSessionFactory的方法
- 加载核心配置文件获取(一般都是这种方法):将核心配置文件转成输入流,
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
xml中是Mybatis的核心配置,与数据库连接的数据源以及事务控制的相关配置都在这里面,下面是最简单的实例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.evader.mapper"/>
</mappers>
</configuration>
- 通过Mybatis提供的预先配置的Configuration实例来加载
大多数情况下都是使用第一种方式构建SqlSessionFactory即通过xml转化为流的形式。如果你不想使用上述方式,Mybatis还提供了Java API来构建。
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(Usermapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
由于 Java 注解的一些限制以及某些 MyBatis 映射的复杂性,要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XML 配置 引用自Mybatis官网的一段话
获取SqlSession
SqlSession是操作数据库的对象,使用时有两种写法
- 早期写法:直接通过sqlSession来执行方法
SqlSession session = sqlSessionFactory.openSession();
User user = (User) session.selectOne("com.evader.UserMapper.selectById", 1);
- 常用写法:通过sqlSession获取对应的映射文件实例,通过具体实例来操作数据库
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1);
小结:第一种写法的方法写在字符串中存在硬编码问题且可能写错,第二种方法可读性高且有IDEA提示不会出现写错的情况
简单的入门案例
先看看简单的映射文件(mapper.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.evader.mapper.UserMapper">
<select id="selectById" parameterType="java.lang.Integer" resultType="com.evader.pojo.User">
select * from User where id = #{id}
</select>
</mapper>
测试代码
@Test
public void selectById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1);
System.out.println(user);
}
效果

作用域与生命周期
??这里要讲的是Mybatis中涉及的常用类的生命周期,以及由生命周期延伸出对应的作用域应该是什么,之所以有这部分内容是因为如果没有恰当的使用Mybatis所提供的类,会造成性能浪费,并发引起的相关问题。
- SqlSessionFactoryBuilder:该类可以生成SqlSessionFactory的类,我们知道SqlSessionFactory是一个工厂,工厂一个就好,多个工厂会造成浪费。所以作用域应该是局部变量。
- SqlSessionFactory:工厂一旦被创建就应该一直存在并且只存在一个,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。所以它的作用域应该是全局变量,常见的实现方式是单例模式。
- SqlSession:每一个线程都会有自己sqlSession实例且它是线程不安全的,因此不可共享,所以SqlSession最好的作用域是请求/方法作用域。除此之外还需注意用完后需要及时关闭,阿里开发手册中明确说明类似示例要在finally中的第一行关闭。
XML配置
属性(properties)
??这是核心配置文件中的第一个标签(Mybatis的核心配置文件有严格的位置要求,不按要求写标签编译都通过不了),它的作用是配置数据源的的几个属性值,官网介绍了三种方式。
- 外部配置db.properties文件,配置数据源使用${}的方式来读取配置的数据
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatisuseSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
- 在标签中的value属性上直接写值
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
- 构建SqlSessionFactory时在build方法中传入参数
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
小结:三种方法存在优先级关系:方法传参>外部文件>核心配置文件中指定的属性
设置(settings)
??settings我们使用时用的并不多,但是及其重要,它会改变Mybatis的运行时行为,这里不展开。后面会详细介绍,只要简单了解有哪些东西即可。
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
|