1.Mybatis核心配置文件
- MyBatis 核心配置文件推荐命名为: mybatis-config.xml
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息
- MyBatis 核心配置文件能配置的内容如下所示:
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
注意元素节点的顺序!顺序不对会报错
1.1 environments节点
environments节点内容如下例所示:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
-
在environments元素中可配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)
-
environment子节点代表其中某一套运行环境,其节点下面主要有dataSource节点以及transactionManager 节点
-
dataSource 节点使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源,并且有3中数据源类型,分别是UNPOOLED、POOLED、JNDI。UNPOOLED代表这个数据源的实现只是每次被请求时打开和关闭连接。POOLED代表这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。JNDI代表这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
-
transactionManager为事务管理器,主要的类型用JDBC与MANAGED ,目前一般都使用JDBC。
1.2 mappers节点
mappers节点的内容如下例所示:
<!--每一个Mapper配置文件都需要在mybatis核心配置文件中定义-->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
- mappers节点可作为映射器 :,来定义映射SQL语句文件
- 既然 MyBatis 的行为其他元素已经配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始,还支持接口映射器,这种映射器方式允许以Java代码的方式注解定义SQL语句,非常简洁
1.3 Properties节点
数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 节点的子元素来传递。所以我们可以在外部创建一个properties 文件并引入该properties 文件便能动态的获取属性值。
如在外面创建db.properties 文件,文件内容如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://xxxxxxxxxx:3306/mybaits_stuudy?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=***********.
随后在Mybatis核心配置文件中的properties 节点引入该外部文件,并在dataSource节点中获取这些值,主要内容如下:
<!--导入properties文件-->
<!--properties内也可定义属性,但当属性名与外部文件冲突时,优先使用外部文件的属性-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
在dataSource 节点中使用properties文件定义的属性
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
1.4 typeAliases节点
typeAliases即类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
第一种使用方法:为某个实体类指定一个别名,那么在其他地方就可以通过别名来代表对应的实体类。
例如:在Mybatis核心配置文件中写上设置别名
<typeAliases>
<typeAlias type="pojo.User" alias="User"/>
</typeAliases>
那么,在Mapper配置文件中就可以使用User来代替pojo.User
<?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">
<!--该配置文件的作用相当于是UserMapper接口的实现类,通过标签可以对应实现具体的方法-->
<!--namespace指定关联的Mapper接口-->
<mapper namespace="dao.UserMapper">
<!--id用来关联Mapper接口下对应的方法,resultType则是指定返回结果集对应的实体类-->
<select id="selectUser" resultType="User">
select * from user
</select>
<select id="getUserById" resultType="User" parameterType="int">
select * from user where id = #{id}
</select>
<!--对象传递参数,要与对象中的属性名对照-->
<insert id="addUser" parameterType="User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="User">
update user set name = #{name},pwd = #{pwd} where id = #{id}
</update>
<delete id="deleteUser" parameterType="User">
delete from user where id = #{id}
</delete>
</mapper>
第二种使用方法:指定一个包名,那么MyBatis 就会在包名下面搜索需要的 Java Bean,在所指定包中的每一个实体类,在没有注解的情况下,会使用该实体类的的首字母小写的类名来作为它的别名。
例如:在Mybatis核心配置文件中写上设置别名
<typeAliases>
<package name="pojo"/>
</typeAliases>
那么,在Mapper配置文件中就可以使用user来代替pojo.User
<?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">
<!--该配置文件的作用相当于是UserMapper接口的实现类,通过标签可以对应实现具体的方法-->
<!--namespace指定关联的Mapper接口-->
<mapper namespace="dao.UserMapper">
<!--id用来关联Mapper接口下对应的方法,resultType则是指定返回结果集对应的实体类-->
<select id="selectUser" resultType="user">
select * from user
</select>
<select id="getUserById" resultType="user" parameterType="int">
select * from user where id = #{id}
</select>
<!--对象传递参数,要与对象中的属性名对照-->
<insert id="addUser" parameterType="user">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="user">
update user set name = #{name},pwd = #{pwd} where id = #{id}
</update>
<delete id="deleteUser" parameterType="user">
delete from user where id = #{id}
</delete>
</mapper>
如果指定的包中的实体类有@Alias注解,那么该实体类的别名就为注解的值。如在pojo.User类上方加上注解@Alias(user11),那么该类的别名就为user11。
1.5 setting节点
一个配置完整的 settings 元素的示例如下:
<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>
其中比较重要的为:
具体设置可参阅官网文档:mybatis3官方文档
1.6其他配置
- 类型处理器
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型 - 对象工厂
每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现
2.Mapper配置文件
<?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">
<!--该配置文件的作用相当于是UserMapper接口的实现类,通过标签可以对应实现具体的方法-->
<!--namespace指定关联的Mapper接口-->
<mapper namespace="dao.UserMapper">
<!--id用来关联Mapper接口下对应的方法,resultType则是指定返回结果集对应的实体类-->
<select id="selectUser" resultType="pojo.User">
select * from user
</select>
<select id="getUserById" resultType="pojo.User" parameterType="int">
select * from user where id = #{id}
</select>
<!--对象传递参数,要与对象中的属性名对照-->
<insert id="addUser" parameterType="pojo.User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="pojo.User">
update user set name = #{name},pwd = #{pwd} where id = #{id}
</update>
<delete id="deleteUser" parameterType="pojo.User">
delete from user where id = #{id}
</delete>
</mapper>
namespace中文意思:命名空间,作用如下:
1.namespace的命名必须跟某个mapper接口同名
2.mapper接口中的方法与映射文件中sql语句id应该一一对应
3.namespace和子元素的id联合保证唯一 , 区别不同的mapper
4.绑定DAO接口
5.namespace命名规则 : 包名+类名
Mapper配置文件其实可以理解为对应Mapper接口的实现类,而在使用过程中,也是通过该配置文件来构造出Mapper接口的实现类的对象,从而才能进行数据库的CRUD。
3.生命周期和作用域
mybatis的运行流程如下图所示:
- SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。换句话说,SqlSessionFactoryBuilder 对象在方法调用完毕之后就应该在内存中撤销掉。
你可以重用SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。 - SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。此外,SqlSessionFactory 最主要的作用其实就是创建SqlSession对象 - SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。换句话说,SqlSession对象在方法调用完毕之后就应该在内存中撤销掉。