前言
在使用MyBatis进行开发的时候,编写mybatis-config.xml(命名随意)这个核心配置文件显得十分重要;它涉及到我们业务操作的方方面面,今天我们就结合官方文档进行相关讲解。
1. 初探核心配置文件
[1] 官方文档中的具体位置
[2] 相关使用例子:
<?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>
<!--导入外部配置文件-->
<properties resource="db.properties"/>
<!--可以给实体类起别名-->
<typeAliases>
<package name="com.gs.pojo"/>
</typeAliases>
<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}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- <mapper resource="com/com.com.gs/dao/UserMapper.xml"/>-->
<!--<mapper class="com.com.com.gs.dao.UserMapper"/>-->
<package name="com.gs.dao"/>
</mappers>
</configuration>
[3] 我们可以从例子中发现configuration的标签中是enviroments,我们不妨推断Mybatis可以配置多套环境。
注意点:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境。
[4] 接着观察transactionManager标签,这是配置我们的事务处理器,Mybatis默认使用的是JDBC,
而dataSource表示我们使用的数据源,默认类型为 POOLED
2. 细究各个配置
上面所讲的配置项相对简单,固定;下面所阐述的是我们开发中经常使用且灵活变化的配置项
[1] 属性 (properties)
作用:我们可以通过properties属性来实现引用配置文件,这些属性可以在外部进行配置,并可以进行动态替换。
也就是我们进行properties有两种方式,一种是在使用外部引入和properties标签下进行嵌套结合;另外一种是直接引入外部配置文件(推荐使用)
第一种方式:在properties标签下进行嵌套
<1> 编写一个配置文件 db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username = root
<2> 在mybatis-config.xml进行引用(这里指的嵌套使用是指上面某些项不写,然后在property中编写)
<!--导入外部配置文件-->
<properties resource="db.properties">
<property name="" value=""/>
</properties>
第二种方式就是直接引入外部文件,不嵌套使用(这种方式管理更加便捷,推荐使用)
这里 引用外部配置文件的值要与配置文件书写的列名一致。
<properties resource="db.properties"/>
<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}"/>
</dataSource>
</environment>
</environments>
注意点:可以在引入外部配置文件中添加一些属性(就像第一种使用方式一样),如果两个配置文件有同一个字段,优先使用外部配置文件的。
[2] 类型别名(typeAliases)
若我们没有配置该属性时,编写xml文件的实体类要使用全类名。
如:resultType=“com.gs.pojo.User”
<select id="getUserList" resultType="com.gs.pojo.User">
select * from user1;
</select>
为了简化上面的写法,我们可以在核心配置文件中进行别名的配置。
- 类型别名可为 Java 类型设置一个缩写名字。
- 它仅用于 XML 配置,意在降低冗余的全限定类名书写
共有两种方式:
<1> 直接在mybatis-config.xml中进行相关实体类的全类名配置
<!--可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.gs.pojo.User" alias="User"/>
</typeAliases>
在相关的Mapper.xml进行引用
<select id="getUserList" resultType="User">
select * from user1;
</select>
<2> 我们也可以只指定一个包名,MyBatis会在包名下面搜索需要的JavaBen(扫描是实体类的包中,这个类的别名,引用时推荐使用首字母小写,不过没有强制要求)
<typeAliases>
<package name="com.gs.pojo"/>
</typeAliases>
引用:
<select id="getUserList" resultType="user">
select * from user1;
</select>
使用场景:
- 在实体类比较少的时候,使用第一种方式
- 如果实体类十分多,建议使用第二种
- 第一种可以DIY别名,第二种则不行; 如果非要修改,需要在实体类上增加注解
@Alias("user")
public class User {
[3] 设置(settings)
这是Mybatis中极为重要的调整设置,它们会改变Mybatis的运行时行为
官方中的配置项解释的十分清楚,可以进行相关查阅
这里介绍两个我们开发中最常用的设置
<1> mapUnderscoreToCamelCase:开启驼峰命名,即解决我们实体类中属性名与数据库中的列名不一致的问题。
数据库的名字: user_Id 实体类的名字:userId (这时我们需要配置该项,否则取不到对应的值)
<2> 配置日志工厂 logImpl,这里是方便我们查看输出日志排查错误,可以理解我们平常使用的System.out;
下面使用的值为STDOUT_LOGGING则为我们标准的日志输出,比较常用的还有Log4j;
<setting name="logImpl" value="STDOUT_LOGGING"/>
[4] 映射器(mappers)
官方文档:
我们使用隐射器时共有三种方式:
相关的dao层文件路径
方式一:使用相对于类路径的资源引用(推荐使用)
<mappers>
<mapper resource="com/gs/dao/UserMapper.xml"/>
</mappers>
对类名和Mapper.xml文件的位置没有任何限制
方式二:使用class文件绑定注册
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="com.gs.dao.UserMapper"/>
</mappers>
使用这种方式的注意点:
- 接口和它的Mapper配置文件必须同名
- 接口和它的Mapper配置文件必须在同一个包下
文件的命名和摆放位置:
方式三:使用扫描包进行注入绑定
<mappers>
<package name="com.gs.dao"/>
</mappers>
使用这种方式的注意点:
- 接口和它的Mapper配置文件必须同名
- 接口和它的Mapper配置文件必须在同一个包下
这三种方式各有各的优势,使用上也没有所谓的优劣之分,只不过第一种对我们配置文件的命名和它所放的位置没有特殊限定,相对比较灵活。
[5] 其他设置(使用相对较少)
详情可参考官方文档
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- mybatis-generator-core
- mybatis-plus
- 通用mapper
3. 生命周期和作用域
不同作用域和生命周期类别是至关重要的,因此错误的使用会导致非常严重的并发问题。
下面以一张图简单描述一下我们mybatis开发中的流程
我们开发时首先要编写一个Mybatis-config.xml的配置文件,这时候系统可以通过SqlSessionFactoryBuilder读取配置文件后,获取相关的配置项,构建出我们的SqlSessionFactory,一个SqlSessionFactory可以创建多个SqlSession会话,它能帮助我们完成多个业务层上的Sql Mapper实现。
记住这里面的每一个Mapper就对应我们编写的一个具体接口,即我们的具体业务。
这是我们创建Mybatis相关对象的工具类
package com.gs.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @Auther: Gs
* @Date: 2020/6/5
* @Description: com.com.com.gs.com.com.com.gs.utils
* @version: 1.0
*/
//sqlSessionFactory ---> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try {
//使用mybatis的第一步:获取SqlSessionFactory的对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/*
既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
*/
public static SqlSession getSession(){
return sqlSessionFactory.openSession(true);
}
}
解析:
[1] SqlSessionFactoryBuilder:
- 一旦创建了SqlSessionFactory,就不再需要Builder这个对象了,所以我们可以把它设置为局部变量或使用静态代码块(也就是我们只需实例化出一个SqlSessionFactoryBuilder:对象)
如上面所写的
private static SqlSessionFactory sqlSessionFactory;
static{
try {
//使用mybatis的第一步:获取SqlSessionFactory的对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
[2] SqlSessionFactory
- 可以通俗的理解为我们的数据库连接池
- SqlSessionFactory一旦创建就应该在运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
- 因此SqlSessionFactory的最佳作用域是应用层面上的,这种实现可以通过使用单例模式或静态单例模式。
[3] SqlSession
- 相当于连接池的一个请求
- SqlSession的实例不是线程安全的,因此不能被共享的,所以它的最佳作用与是请求或方法作用域
- 用完之后需要赶紧关闭,否则资源会被占用。
小结:
从往常的学习中,我们不难发现官方文档使我们最好的伙伴,我们应该多借助官方文档进行学习,相关方面的文章是为了让我们更好的理解。还是以狂神的那句话作为结尾吧,人生没有白走的路,因为每一步都算数。