文章目录
- 一、简介
- 二、各个标签
- 2.1 properties(属性)
- 2.2 settings(设置)
- 2.3 typeAliases(类型命名)
- 2.4 typeHandlers(类型处理器)
- 2.5 plugins(插件)
- 2.6 environment(环境)
- 2.7 databaseIdProvider(数据库厂商标识)
- 2.8 mappers(映射器)
学习地址🔗
- https://www.bilibili.com/video/BV1mW411M737
- https://www.bilibili.com/video/BV1NE411Q7Nx
- 官网文档
一、简介
💬概述:MyBatis全局配置文件中包含了对MyBatis的行为有显著影响的设置(settings)和属性(properties)信息
🔑配置文件中的结构图
💡 在全局配置文件中添加上图结构中的各个标签时,必须按照图中结果从上往下的顺序添加,不然会报错
二、各个标签
2.1 properties(属性)
💬概述:在MyBatis全局配置文件中可以添加<properties>
标签,用于引入或设置属性值。一般用于引入数据库连接或数据库连接池的相关属性
🔑为属性赋值的两种方式
① 在<properties>
标签中使用resource
属性获取url
属性引入外部属性文件(.properties)
<properties resource="jdbc.properties"/>
❓ resource属性 🆚 url属性
resource
属性:用于引入类路径下的文件,属性值为文件在类路径下的路径,用/
分隔每一个包和文件,如【com/key/mybatis/a.properties】url
属性:用于引入网络资源文件或磁盘目录下的文件,属性值为文件在网络上的链接地址或磁盘目录下的路径
② 在<properties>
标签内添加<property>
标签,<property>
标签中使用name
和value
属性设置属性
<properties>
<property name="prop.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="prop.url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="prop.username" value="root"/>
<property name="prop.password" value="1234"/>
</properties>
🔑获取属性值的方法:${属性名(键)}
(类似与EL表达式,一般在数据源<dataSource>
标签中获取)
<dataSource type="POOLED">
<property name="driver" value="${prop.driver}"/>
</dataSource>
🔑获取属性值的顺序:如果在<properties>
标签中不止一个地方设置了属性,或对同一个属性通过不同方式进行赋值,则MyBatis会按照下面的顺序来获取属性值
- 首先获取的是
<properties>
的子标签<property>
中设置的属性值 - 然后根据
<properties>
标签通过resource
或url
属性中引入的外部属性值,并覆盖已获取的同名属性的值 - 最后获取由方法参数传递过来的属性值,同样会覆盖已获取的同名属性的值
2.2 settings(设置)
💬概述:在全局配置文件中可以添加<settings>
标签,该标签是MyBatis中重要的全局调整设置,用于设置MyBatis运行中的各种行为和参数值
🔑可以设置的部分参数
可以设置的参数 | 参数值类型 | 默认值 | 解释 |
---|---|---|---|
cacheEnabled | boolean | true | 所有映射器中配置的缓存的全局开关 |
lazyLoadingEnabled | boolean | false | 延迟加载的全局开关;开启(参数值为true)时,所有关联对象都会延迟加载 |
useColumnLabel | boolean | true | 使用列标签代替列名 |
defaultStatementTimeout | 正数值 | null | 连接数据库时的超时时间 |
mapUnderscoreToCamelCase | boolean | false | 是否开启自动驼峰命名映射(下划线命名转成驼峰命名); |
❓ 关于自动驼峰命名映射
- 如果开启自动驼峰命名映射(参数值设置为true),MyBatis就会自动将数据库表中带下划线的字段名转成JavaBean中对应的使用驼峰命名法命名的成员变量名(如user_name <–> userName)
- 如果JavaBean中的成员变量名不遵循驼峰命名法,而与之对应的数据库表中的字段名遵循下划线命名,此时开启自动驼峰命名映射也能映射成功(JavaBean中成员变量能获取到表中对应字段的值),如user_name <–> username(n没有大写),这种情况也能映射成功
- 开启该设置后,SQL语句的书写中就不用使用为每一个字段取别名的方式避免表字段与JavaBean成员变量不一致的问题
🔑使用:在<settings>
标签中添加子标签<setting>
,<setting>
中通过name
和value
属性设置各个参数(下面是官方文档中提供的例子)
<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>
2.3 typeAliases(类型命名)
🔑添加标签:在全局配置文件中可以添加<typeAliases>
标签,用于给Java类(全类名)设置别名
🔑作用:在全局配置文件中给某个JavaBean的全类名设置一个别名,然后在SQL映射文件中就可以直接通过JavaBean的别名来代替全类名,从而简化映射文件的类名的书写和JavaBean的引入
- 全局配置文件中
<!-- 为JavaBean设置别名 -->
<typeAliases>
<!-- 为单个JavaBean设置别名 -->
<typeAlias type="com.key.mybatis.entity.User" alias="u"/>
</typeAliases>
<!-- +------------------------------------------------------------------------------------+ -->
- SQL映射文件中
<select id="selectUser" resultType="u">
select *
from `user`
where `user_id` = #{user_id}
</select>
🔑为Java类设置别名的两种方式
① 为单个JavaBean设置别名:在<typeAliases>
标签中添加子标签<typeAlias>
,然后在<typeAlias>
中为某一个JavaBean指定别名,可以添加多个<typeAlias>
标签,一个<typeAlias>
只能为一个JavaBean指定别名
<!-- 为JavaBean设置别名 -->
<typeAliases>
<!-- 为单个JavaBean设置别名 -->
<typeAlias type="com.key.mybatis.entity.User" alias="u"/>
</typeAliases>
🔺
<typeAlias>
标签中两个属性
- type:指定JavaBean的全类名
- alias:为
type
属性中指定的JavaBean设置别名,可以不添加该属性,不添加表示为JavaBean设置默认别名
② 批量设置别名:在<typeAliases>
标签中添加子标签<package>
,然后在<package>
中通过name
属性添加某个包,表示为该包下以及该包的子包下的所有JavaBean都设置别名,实现批量设置
-
为每一个JavaBean都取默认的别名:如果只在
<package>
标签中设置了包名,则MyBatis会给该包下以及子包下所有JavaBean都取上默认别名<!-- 为JavaBean设置别名 --> <typeAliases> <!-- 批量设置别名 --> <package name="com.key.mybatis.entity"/> </typeAliases>
💡 默认别名就是JavaBean类名,因为别名不区分大小写,所以引用在映射文件中引用JavaBean时,大写小写两种方式书写别名来引用JavaBean都可(类名的任意字母大小写都可),如User --> user/User/USER/uSEr…但一般通过类名小写来引用
-
采用
@Alias
注解为某一个JavaBean指定别名:在使用<package>
标签设置了包名(即采用批量设置别名)的前提下(相当于开启注解的组件扫描),可以通过@Alias
注解为包下的某一个JavaBean再重新设置一个别名(不采用默认的别名)@Alias("u") public class User { private Integer userid; private String username; private String password; public User() { } // other codes... }
❓ 为什么需要使用
@Alias
注解:如果不使用@Alias
注解,而是采用为每一个JavaBean设置默认的别名,则有可能会产生别名冲突,因为在不同包下可以创建名字一样的类,而<package>
标签为不同子包下类名一样的JavaBean设置的默认别名也是一样的,因此就会产生冲突,而@Alias
注解可以单独为某一个JavaBean设置与默认别名不一样的别名,从而解决默认别名冲突的问题
🔑Java中的常见内部类对应的别名:MyBatis已经为Java中一些常见内部类封装了相对应的别名,同样是不区分大小写,所以我们在对自定义的JavaBean设置的别名不能与内部类别名一样
💡 内部类对应的具体别名可参见官方文档;开发中不推荐使用类型别名,建议在映射文件中使用对每一条SQL语句指定完整的JavaBean全类名,虽然比较麻烦,但能清晰看到SQL结果集对应的JavaBean,且通【过ctrl+鼠标左键】能快速访问到对应JavaBean
2.4 typeHandlers(类型处理器)
💬概述:全局配置文件中可以设置多个类型处理器,不同类型处理器对应不同的标签,也对应不同的Java内部类或数据类型,以及对应数据库兼容的数据类型,如<StringTypeHandler>
--> java.lang.String
--> CHAR/VARCHAR
🔑作用:在MyBatis对SQL语句进行预编译处理时,MyBatis会调用类型处理器以合适的方式对数据库兼容的数据类型和Java中对应的数据类型进行相互转化,实现为SQL语句设置参数值(填充占位符)、将结果集转换成JavaBean(或从结果集中获取值)
2.5 plugins(插件)
💬概述:插件是MyBatis提供的一个强大机制,我们可以通过插件修改MyBatis一些核心行为
🔑作用:插件基于动态代理机制,可以介入(拦截)MyBatis中四大对象的任何一个方法
❓ 四大对象:Executor(执行器)、ParameterHandler(参数处理器)、ResultSetHandler(结果集处理器)、StatementHandler(SQL语句处理器),它们的具体方法可参见官网文档
2.6 environment(环境)
🔑添加标签:在全局配置文件中可以添加<environments>
标签配置环境,比如开发、测试等环境,每一个环境通过子标签<environment>
来设置具体参数
🔑配置环境细节
-
<environment>
的id
属性:环境的唯一标识,一般设置属性值设置为development
(开发)、test
(测试) -
<environments>
的default
属性:通过环境的唯一标识(id
值)指定当前工程使用的环境,通过default
属性可以快速切换当前环境 -
<environment>
标签中两个必须添加的子标签💡 实际开发中使用Spring管理数据源和事务,这里只是了解即可
①
<transactionManager>
标签<transactionManager type="JDBC"/>
-
作用:设置当前环境的事务管理器
-
type
属性:用于指定事务管理器的类型,有三种属性值选取属性值 对应类型 解释 JDBC JdbcTransactionFactory MyBatis提供的类型别名;表示使用JDBC中的事务提交和回滚操作,依赖于从数据源 <dataSource>
中获取的连接来管理事务MANAGED ManagedTransactionFactory MyBatis提供的类型别名;表示不使用事务提交和回滚操作,让容器(应用服务器)来管理事务的整个生命周期 自定义类的全类名(或类型别名) 自定义类型 可以自定义一个事务管理器——创建一个类实现 TransactionFactory
接口❓ 关于MyBatis提供的两个属性值
-
MyBatis提供的两个
type
属性值——JDBC
和MANAGED
,本质上是JdbcTransactionFactory
和ManagedTransactionFactory
的别名,这两个类都是TransactionFactory
的实现类 -
MyBatis在自带的全局配置类
Configuration
中对很多类设置了别名,包括上面两个类,还有数据源的类型以及数据库厂商标识中的类型👇
-
②
<dataSource>
标签(数据源)<dataSource type="POOLED"> <property name="driver" value="${prop.driver}"/> <property name="url" value="${prop.url}"/> <property name="username" value="${prop.username}"/> <property name="password" value="${prop.password}"/> </dataSource>
-
作用:设置数据源,从数据源中获取数据库连接
-
type
属性:用于指定数据源的类型,有四种属性值选取属性值 对应类型 解释 UNPOOLED UnpooledDataSourceFactory MyBatis提供的类型别名;表示不使用数据库连接池技术 POOLED PooledDataSourceFactory MyBatis提供的类型别名;表示使用MyBatis中默认的数据库连接池技术 JNDI JndiDataSourceFactory MyBatis提供的类型别名;表示在EJB或应用服务器等容器中查找指定的数据源 自定义类的全类名 自定义类 自定义一个数据源——创建一个类,实现 DataSourceFactory
接口,并实现接口中的方法,用于获取数据源(通过其他数据库连接池获取数据源) -
<property>
子标签:为数据源中四个属性(driver、url、username、password)赋值,赋值方式可以通过${属性名}
的方式获取外部属性值,也可以直接在书写属性值
-
2.7 databaseIdProvider(数据库厂商标识)
💬概述:在全局配置文件中可以添加<databaseIdProvider>
标签获取并解析不同的数据库厂商标识,也可以为各个数据库厂商的标识取别名
❓ 数据库厂商标识的获取
- 数据库厂商的标识可以通过数据库驱动的连接对象获取,在
java.sql.Connection
类中有一个getMetaData()
方法,该方法可以获取一个DatabaseMetaData
类型的对象,而DatabaseMetaData
类中有一个getDatabaseProductName()
方法,该方法返回值就是对应数据库厂商的标识- 有些数据库厂商的标识比较长,且可能相同的产品在不同版本下返回不同的值,所以最好给厂商设置别名
🔑作用:通过<databaseIdProvider>
标签设置不同的数据库厂商别名,在SQL映射文件就可以根据不同的厂商别名获取相应的数据库连接,并执行相应的SQL语句
🔑<databaseIdProvider>
标签介绍
-
type
属性:用于获取数据库厂商的标识,有两种属性值选取属性值 对应类型 解释 DB_VENDOR VendorDatabaseIdProvider MyBatis提供的类型别名;标识采用MyBatis自带的 VendorDatabaseIdProvider
类来获取并解析数据库厂商的标识自定义类的全类名 自定义类 可以自定义一个解析厂商标识的类,需要实现 DatabaseIdProvider
接口 -
<property>
子标签:为各个数据库厂商标识设置别名,标签的两个属性分别为① name --> 指定数据库厂商标识,如MySQL、Oracle、SQL Server等
② value --> 为对应的数据库厂商设置别名
🔑使用(这里用MySQL数据库厂商来演示)
① 在<environment>
环境配置中添加数据库厂商对应的环境,包括事务管理器和数据源信息,同时通过<environments>
中的defualt
属性选择相对应的环境
<environments default="development">
<environment id="development">
<dataSource type="POOLED">
<property name="driver" value="${prop.driver}"/>
<property name="url" value="${prop.url}"/>
<property name="username" value="${prop.username}"/>
<property name="password" value="${prop.password}"/>
</dataSource>
</environment>
</environments>
② 在全局配置文件中添加<databaseIdProvider>
标签,标签中type
属性值设置为DB_VENDOR
,然后在标签内添加<property>
子标签,为对应的数据库厂商标识设置更简洁的别名
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlServer"/>
</databaseIdProvider>
③ 在SQL映射文件中的SQL语句标签(如<select>
)中,添加<databaseId>
属性,该属性用来标识执行SQL语句的数据库厂商,属性值就是全局配置文件中为对应数据库厂商设置的别名
<select id="getAllUsers" resultType="com.key.mybatis.entity.User" databaseId="mysql">
select *
from `user`
</select>
🔑SQL语句与数据库厂商的匹配规则
- 如果在全局配置文件中没有添加
<databaseIdProvider>
标签,则SQL映射文件中的SQL语句标签的databaseId
属性值为null(默认值) - 如果在全局配置文件中添加了
<databaseIdProvider>
标签且SQL语句标签中也添加了databaseId
属性,则MyBatis会根据<databaseIdProvider>
中设置的数据库厂商标识(即<property>
标签中的name
属性值)以及标识的别名与SQL语句标签的databaseId
属性值进行匹配,如果匹配成功,则SQL语句就会与对应的数据库厂商进行绑定,如果匹配失败,则databaseId
依旧是null - MyBatis会根据当前环境设置的数据源信息,在映射文件中找到与数据源对应的数据库厂商绑定成功的SQL语句和没有添加
databaseId
属性的SQL语句,然后加载;其他有添加databaseId
属性但databaseId
为null的SQL语句,以及有添加databaseId
且不为null但与当前环境中设置的数据源不匹配的SQL语句,都不会被加载 - 如果映射文件中有两个
id
值、SQL语句、结果集类型都一样的SQL语句标签,但一个有添加databaseId
属性,一个没有添加,则MyBatis在加载时会选择前者(更精确),舍弃后者,所以这种情况下不会报错
2.8 mappers(映射器)
💬概述:全局配置文件中可以添加<mappers>
标签,表示映射器,用于在全局配置文件中注册SQL映射文件或持久层接口
🔑注册映射文件或接口的方式
-
注册单个映射文件或接口:在
<mappers>
标签中添加<mapper>
子标签,子标签中添加对应属性来注册文件或接口-
注册单个映射文件:在
<mapper>
标签中添加resource
属性或url
属性,属性值为映射文件的路径(resource
与url
的区别跟<properties>
属性标签中的一样)<mappers> <!-- 注册类路径下的映射文件 --> <mapper resource="com/key/mybatis/dao/UserMapper.xml"/> <!-- 注册磁盘目录下的映射文件 --> <mapper url="file:///D:/UserMapper.xml"/> </mappers>
-
注册单个持久层接口:在
<mapper>
标签中添加class
属性,属性值为接口的全类名;该注册方式有两种情况<mappers> <!-- 注册接口 --> <mapper class="com.key.mybatis.dao.UserDao"/> </mappers>
① 既有持久层接口,又有与其对应的SQL映射文件:这种情况下需要将持久层接口和对应的映射文件放在同一个目录下,且接口名和映射文件名要保持一致
❓ 关于接口文件和映射文件的位置
- 问题:工程中的资源文件一般放在src/main/resource目录下,持久层接口放在src/main/java目录的dao包下,而使用第一种方式时接口和映射文件又必须在同一目录下
- 解决方法:在src/main/resource目录下创建与接口所在包结构一样的包结构,如src/main/resource/com/dao/UserDao.xml <–> src/main/java/com/dao/UserDao.java(在resource目录下建立目录会遇到的问题解决:IntelliJ IDEA的Resources下创建包)
- 为什么:因为maven工程在编译打包时会将java和resource两个目录下的全部文件以及文件所在包都拷贝到target/classes目录下,相同的包结构自然会进行合并,因此在工程运行后,映射文件和接口文件就会被打包到同一个目录(包)下
② 只有持久层接口,无对应的SQL映射文件:这种情况下对接口的位置和接口名没有限制,但需要在接口对应方法中添加SQL语句注解,注解中直接书写SQL语句,实现SQL语句与接口方法的绑定
public interface UserDaoAnno { @Select("select * from user") List<User> getAllUsers(); }
❓ 关于第二种方式
- SQL语句注解:SQL语句注解类似于映射文件中的SQL语句标签,增删改查对应的注解分别为
@Insert
、@Delete
、@Update
、@Select
,在注解上可以直接书写SQL语句,如@Select("select * from user")
- 该方式又会将SQL语句与Java代码耦合在一起,而且对于比较复杂的SQL语句,直接写在注解上会更加麻烦和混乱,因此不推荐使用这种方式
-
-
批量注册:在
<mappers>
标签中添加<package>
子标签,子标签中可以通过name
属性添加包名,实现对该包下以及该包的子包下全部持久层接口进行注册<mappers> <!-- 批量注册 --> <package name="com.key.mybatis.dao"/> </mappers>
💡 因为批量注册实际上也是对接口进行注册,所以满足注册接口的两种情况其中一种才能成功注册,其他情况下的接口(即使是命名为XxxDao)都不会被注册