📢📢📢📣📣📣
哈喽!大家好,我是【一心同学】,一位上进心十足的【Java领域博主】!😜😜😜
✨【一心同学】的写作风格:喜欢用【通俗易懂】的文笔去讲解每一个知识点,而不喜欢用【高大上】的官方陈述。
✨【一心同学】博客的领域是【面向后端技术】的学习,未来会持续更新更多的【后端技术】以及【学习心得】。
✨如果有对【后端技术】感兴趣的【小可爱】,欢迎关注【一心同学】💞💞💞
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
一心同学将在这一章为大家详解MyBatis的XML配置文件,感受其中的奇妙之处。
目录
1.2创建一个properties文件配置好相应的数据库连接信息,由配置文件properties 元素读取
3.1通过在typeAliases下指定一个全限定类名,以及其对应的别
3.2通过指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
配置文档的顶层文档如下:
注意:其顺序不能够随意改变,否则会报错
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
1、properties(属性)
作用:对数据库信息的管理。
特性:可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递
为dataSource元素配置
目前最常用的两种配置方式分别是
1.在properties 元素的子元素中设置数据库信息
2.创建一个properties文件配置好相应的数据库连接信息,由配置文件properties 元素读取
1.1在properties 元素的子元素中设置数据库信息
<properties resource="db.properties">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_blog?useSSL=true&useUnicode=true&characterEncoding=UTF-8\
&autoReconnect=true&failOverReadOnly=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
1.2创建一个properties文件配置好相应的数据库连接信息,由配置文件properties 元素读取
db.properties文件:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_blog?useSSL=true&useUnicode=true&characterEncoding=UTF-8\
&autoReconnect=true&failOverReadOnly=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=root
password=123456
properties 元素进行解析:
<properties resource="db.properties">
</properties>
通过这两种方式都可以进行配置数据库的连接,最后我们只需要在dataSource下进行引用即可,如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
看到这里,大家可能会想到一个问题,如果同时运用了这两种方式,即一个属性在不只一个地方进行了配置,那么,MyBatis将会如何加载呢:
MyBatis加载顺序:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
也就是说MyBatis会先读取第一种方式,接着再读取第二种方式,而且如果MyBatis发现两种方式有相同的属性名,那么MyBatis会选择用第二种方式也就是读取相应路径下的属性会覆盖properties 元素体内指定的属性。
故两种方式的优先级可由此得出:
优先级高的是resource/url 属性中指定的配置文件,最低优先级的则是 properties 元素中指定的属性。
额外配置:如果一个元素的值没有被配置,那么可以将该属性的值设为给定的默认值。
前提:这个特性默认是关闭的。要启用这个特性,需要添加一个特定的属性来开启这个特性。
<properties resource="db.properties">
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/><!--开启这个特性-->
</properties>
使用:
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${username:root}"/><!-- 如果username没有配置,那么将使用root作为用户名 -->
<!-- ... -->
</dataSource>
2、设置(settings)
settings是MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为,常见的设置名,描述,默认值如下:
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true | false | false |
aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods )。 | true | false | false (在 3.4.1 及之前的版本中默认为 true) |
multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。
| NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) | 未设置 (null) |
safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true | false | False |
safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
一个完整的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>
3、类型别名(typeAliases)
作用:可为 Java 类型设置一个缩写名字,仅用于 XML 配置,意在降低冗余的全限定类名书写。
我们在使用
有两种别名方式:
- 通过在typeAliases下指定一个全限定类名,以及其对应的别名
- 通过指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
3.1通过在typeAliases下指定一个全限定类名,以及其对应的别名
<typeAliases>
<typeAlias type="com.yixin.pojo.Blog" alias="Blog"/>
</typeAliases>
当我们这样配置时,Blog可以用在任何使用 com.yixin.pojo.Blog的地方。
例如:
这样在里面的返回结果resultType就不需要写成:com.yixin.pojo.Blog。可以大大减少类完全限定名的冗余。
<mapper namespace="com.yixin.dao.BlogMapper">
<select id="selectBlogAll" resultType="Blog">
select * from blog
</select>
</mapper>
3.2通过指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
特性:
1、类名没有注解:每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;
2、类名有注解,则别名为其注解值。见下面的例子:
@Alias("Blog")
public class Blog {
private int id;
private String name;
private String pwd;
//set,get,无参,有参
}
常见的 Java 类型别名:
注意:不区分大小写的,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
4.类型处理器(typeHandlers)
MyBatis类型转换机理:
在数据库中存储时往往需要转换成数据库对应的类型,并且在从数据库中取出来时也需要将数据库类型转换为javabean中的对应类型。无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
如MyBatis内置的TypeHandlers
BooleanTypeHandler:用于 java 类型 boolean,jdbc 类型 bit、boolean
ShortTypeHandler:用于 java 类型 short,jdbc 类型 SMALLINT
解决不支持的类型转换问题:
如果我们要处理不支持的或非标准的类型就需要重写类型处理器或创建你自己的类型处理器。
具体做法日后一心同学会单独出一篇博客进行讲解,因为里面的内容是比较多的。目前的学习使用只需了解即可。
5.对象工厂(objectFactory)
- MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。
- 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过有参构造方法来实例化。
- 默认的对象工厂不做其他任何的处理。如果我们想在创建实例化一个目标类的时候做点啥其他的动作,可以继承DefaultObjectFactory,覆写父类方法,并在mybatis-config.xml中注册配置这个对象工厂类。
一心同学刚开始看对象工厂的时候,就是一脸懵逼,后来通过多次的上机实验,我终于悟了。
我把对象工厂objectFactory的运作分为两步:
1、实例化目标类(相当于提供了一个模板)
2、将实例化后的目标类传递给setProperties 方法,而setProperties的作用就是把从数据库调来的信息装入这个模板中。
接下来请看我的操作:
首先写一个自定义对象工厂:
creat():实例化目标类
setProperties():装载
package com.yixin.objectfactory;
import com.yixin.pojo.Blog;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
public class MyObjcetFactory extends DefaultObjectFactory {
@Override
public Object create(Class type) {
if(type.equals(Blog.class)){
Blog blog=(Blog)super.create(type);
blog.setPwd("666666");//将每一个实例化目标类的密码初始值设为666666
blog.setName("yixin");//将每一个实例化目标类的名称初始值设为yixin
System.out.println(blog);
return blog;
}
return super.create(type);
}
@Override
public <T> boolean isCollection(Class<T> type) {
return super.isCollection(type);
}
@Override
public void setProperties(Properties properties) {
Iterator iterator=properties.keySet().iterator();
while(iterator.hasNext()){
String keyValue=String.valueOf(iterator.next());
System.out.println(properties.getProperty(keyValue));//打印100
}
super.setProperties(properties);
}
}
在xml文件中进行配置这个自定义对象工厂:
<objectFactory type="com.yixin.objectfactory.MyObjcetFactory">
<property name="someProperty" value="100"/>
</objectFactory>
这里的参数传递就是传递给setProperties(Properties properties)
进行测试
@Test
public void test(){
SqlSession sqlSession= MybatisUtils.getSession();
BlogMapper mapper= sqlSession.getMapper(BlogMapper.class);
List<Blog> blogList=mapper.selectBlogAll();
// List<Blog> blogList=sqlSession.selectList("com.yixin.dao.BlogMapper.selectBlogAll");
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}
在此之前,我们先去数据库插入一条数据,这条数据的特点是:有id,name,但是无pwd。根据我们的想法,对象工厂通过创建一个自带默认值的Blog,然后传递给setProperties进行装载。
先在数据库插入这条数据:
insert into blog(id,name) values(4,'object');其pwd是null.
开始测试:
运行结果:
从运行中可以看到100,也就是我们输入的值被打印出来,而id=4的Blog,pwd为666666,测试成功!
6、插件(plugins)
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
那么怎么用的呢?只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
public Object intercept(Invocation invocation) throws Throwable {
// implement pre processing if need
Object returnObject = invocation.proceed();
// implement post processing if need
return returnObject;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
接着在xml文件中进行配置:
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行底层映射语句的内部对象。
7、环境配置(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>
关键点:
- 默认使用的环境 ID(比如:default="development")。
- 每个 environment 元素定义的环境 ID(比如:id="development")。
- 事务管理器的配置(比如:type="JDBC")。
- 数据源的配置(比如:type="POOLED")。
事物管理器transactionManager有两种:type="[JDBC|MANAGED]"
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
8、数据源(dataSource)
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
- driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
- url – 这是数据库的 JDBC URL 地址。
- username – 登录数据库的用户名。
- password – 登录数据库的密码。
- defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
- defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。
9、数据库厂商标识(databaseIdProvider)
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId
属性。[了解即可]
10、映射器(mappers)
- 映射器 : 定义映射SQL语句文件
引入资源方式
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!--
将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
Mapper文件
<mappers>
<mapper resource="com/yixin/dao/BlogMapper.xml"/>
</mappers>
- namespace中文意思:命名空间,作用如下:
- namespace的命名必须跟某个接口同名
- 接口中的方法与映射文件中sql语句id应该一一对应
- namespace和子元素的id联合保证唯一 , 区别不同的mapper
- 绑定DAO接口
- namespace命名规则 : 包名+类名
这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就是每个 SQL 映射文件了。
小结
以上就是【一心同学】对MyBatis配置文件的讲解,太心累了,配置是真的多,建议多动手实操一下,对配置文件的理解会更加深刻,一心同学将会在下一个博客继续讲解mybatis的知识点。