Spring系列教程1.2-Mybites-核心配置

Spring系列教程1.2-Mybites-核心配置
JavaT一 核心对象
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder包含以上方法,常用的有
-
build(InputStream inputStream,String environment,Properties properties)
-
build(Reader reader,String environment,Properties properties)
-
build(Configuration config)
这三个 build
方法用于构建配置对象,区别在于传入的参数类型不同。build(InputStream inputStream, String environment, Properties properties)
通过输入流 InputStream
读取配置文件,适合处理二进制或非文本数据;build(Reader reader, String environment, Properties properties)
则使用 Reader
读取字符流,适合文本配置文件。两者都要求传入 environment
(环境名称)和 properties
(额外的配置项)。而 build(Configuration config)
直接接收一个 Configuration
对象,适用于已经有完整配置实例的情况,无需再提供流、环境或属性,从而简化了配置构建过程。
在示例工程中使用的是第一种 (位于
src/main/java/site/icefox/javaeelearn/Util/DBConn.java
中)
1
2
3 String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用程序执行期间都会存在。如果我们多次创建同一个数据库的SqlSessionFactory对象,那么该数据库的资源将很容易被耗尽。通常每一个数据库都只创建一个SqlSessionFactory对象,所以在构建SqlSessionFactory对象时,建议使用单例模式。
SqlSessionFactory
openSession()方法
方法名称 | 描述 |
---|---|
openSession() | 开启一个事务。 |
openSession(Boolean autoCommit) | 参数autoCommit可设置是否开启事务。 |
openSession(Connection connection) | 参数connection可提供自定义连接。 |
openSession(TransactionIsolationLevel level) | 参数level可设置隔离级别。 |
openSession(ExecutorType execType) | 参数execType有三个可选值。 |
openSession(ExecutorType execType,Boolean autoCommit) | 参数execType有三个可选值。 |
openSession(ExecutorType execType,Connection connection) | 参数ExecutorType有三个可选值。 |
参数autoCommit可设置是否开启事务。
参数connection可提供自定义连接。
参数 execType 有三个可选值:
ExecutorType.SIMPLE:表示为每条语句创建一条新的预处理语句。
ExecutorType.REUSE:表示会复用预处理语句。
ExecutorType.BATCH:表示会批量执行所有更新语句。
SqlSession
SqlSession是MyBatis框架中另一个重要的对象,它是应用程序与持久层之间执行交互操作的一个单线程对象,主要作用是执行持久化操作,类似于JDBC中的Connection。SqlSession对象包含了执行SQL操作的方法,由于其底层封装了JDBC连接,所以可以直接使用SqlSession对象来执行已映射的SQL语句。
每一个线程都应该有一个自己的SqlSession对象,并且该对象不能共享。SqlSession对象是线程不安全的,因此其使用范围最好在一次请求或一个方法中,绝不能将其放在类的静态字段、对象字段或任何类型的管理范围(如Servlet的HttpSession)中使用。SqlSession对象使用完之后,要及时的关闭,SqlSession对象通常放在finally块中关闭,代码如下所示。
1 | SqlSession sqlSession = sqlSessionFactory.openSession(); |
在示例工程中的例子(位于
src/main/java/site/icefox/javaeelearn/Dao/UsersDao.java
中)
1
2
3
4
5
6
7
8
9
10
11
12 public static UsersEntity getUsersByUid(int uid) {
UsersEntity result = null;
// 此处使用try-with-resource语法调用工具类中的getSqlSession()方法获取SqlSession
try (SqlSession sqlSession = DBConn.getSqlSession()) {
// 持久化操作
UsersMapper usersmapper = sqlSession.getMapper(UsersMapper.class);
result = usersmapper.getUserByUid(uid);
} catch (Exception e) {
logger.severe(e.getMessage());
}
return result;
}
二 核心配置文件
2.1 文件结构
<configuration>
元素是整个XML配置文件的根元素,相当于MyBatis各元素的管理员。<configuration>
有很多子元素,MyBatis的核心配置就是通过这些子元素完成的。需要注意的是,在核心配置文件中,<configuration>
的子元素必须按照如下结构顺序进行配置,否则MyBatis在解析XML配置文件的时候会报错。(部分配置项可以省略)
1 |
|
2.2 配置节点
2.2.1 properties
property
中使用${}
来引用配置文件中的值
在示例工程中对应内容(在
src/main/resources/db.dev.properties
中)
1
2
3
4
5
6
7
8
9 <!--=src/main/resources/db.dev.properties -->
# mysql驱动,版本>=80添加cj
mysql.driver=com.mysql.cj.jdbc.Driver
# 数据库连接地址,
mysql.url=jdbc:mysql://localhost:3306/d_mybiteslearn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
# 数据库用户名
mysql.username=root
# 数据库密码
mysql.password=root在
src/main/resources/mybatis-config.xml
中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 <!-- 引入外部配置文件 -->
<properties resource="db.dev.properties"/>
<!-- 默认环境为dev-->
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
#### 2.2.2 settings
用于配置一些参数
``` xml
<settings>
<!-- 是否开启缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 是否开启延迟加载,如果开启,所有关联对象都会延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 是否开启关联对象属性的延迟加载,如果开启,对任意延迟属性的调用都
会使用带有延迟加载属性的对象向完整加载,否则每种属性都按需加载 -->
<setting name="aggressiveLazyLoading" value="true" />
<!-- ... -->
</settings>
2.2.3 typeAliases
核心配置文件若要引用一个POJO实体类,需要输入POJO实体类的全限定类名,而全限定类名比较冗长,如果直接输入,很容易拼写错误。这时可以使用
有如下几种方法配置:
方式一:在
1
2
3
4 <typeAliases>
<typeAlias alias="Users" type="site.icefox.javaeelearn.Entity.UsersEntity"/>
<typeAlias alias="Student" type="site.icefox.javaeelearn.Entity.StudentsEntity"/>
</typeAliases>
方式二:通过自动扫描包的形式自定义别名。
在示例工程中如下( In
src/main/resources/mybatis-config.xml
)
1
2
3 <typeAliases>
<package name="site.icefox.javaeelearn.Entity"/>
</typeAliases>
除了可以使用
2.2.4 environments
MyBatis可以配置多套运行环境,如开发环境、测试环境、生产环境等,我们可以灵活选择不同的配置,从而将SQL映射到不同运行环境的数据库中。不同的运行环境可以通过
MyBatis的运行环境信息包括事务管理器和数据源。
在MyBatis的核心配置文件中,MyBatis通过
元素名称 | 用途 |
---|---|
用于配置运行环境的事务管理器 | |
用于配置运行环境的数据源信息 |
2.2.4.1 transcationManager
类型 | 说明 |
---|---|
JDBC | 此配置直接使用JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务的作用域。 |
MANAGED | 此配置不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。默认情况下,它会关闭连接,但可以将 |
2.2.4.2 daraSource
对于数据源的配置,MyBatis提供了UNPOOLED、POOLED和JNDI三种数据源类型。
-
UNPOOLED
表示数据源为无连接池类型。配置此数据源类型后,程序在每次被请求时会打开和关闭数据库连接。UNPOOLED适用于对性能要求不高的简单应用程。UNPOOLED类型的数据源需要配置5种属性。
属性 | 说明 |
---|---|
driver | JDBC驱动的Java类的完全限定名(并不是JDBC驱动中可能包含的数据源类) |
url | 数据库的URL地址 |
username | 登录数据库的用户名 |
password | 登录数据库的密码 |
defaultTransactionIsolationLevel | 默认的连接事务隔离级别 |
-
POOLED
表示数据源为连接池类型。POOLED数据源利用“池”的概念将JDBC连接对象组织起来,节省了在创建新的连接对象时需要初始化和认证的时间。POOLED数据源使得并发Web应用可以快速的响应请求,是当前比较流行的数据源配置类型。
属性 | 说明 |
---|---|
poolMaximumActiveConnections | 在任意时间可以存在的活动连接数量,默认值:10。 |
poolMaximumIdleConnections | 任意时间可能存在的空闲连接数。 |
poolMaximumCheckoutTime | 在被强制返回之前,池中连接被检出时间,默认值:20000 毫秒。 |
poolTimeToWait | 如果获取连接花费的时间较长,它会给连接池打印状态日志并重新尝试获取一个连接,默认值:20000毫秒。 |
poolPingQuery | 发送到数据库的侦测查询,用来检验连接是否处在正常工作秩序中。默认是“NO PING QUERY SET”。 |
poolPingEnabled | 是否启用侦测查询。若开启,必须使用一个可执行的SQL语句设置poolPingQuery属性,默认值:false。 |
poolPingConnectionsNotUsedFor | 配置poolPingQuery的使用频度。 |
-
JNDI
是一种用于从应用服务器或容器中获取数据库连接的机制。JNDI 数据源通常用于在 Java EE 环境下配置数据源,方便在应用程序中进行数据库连接的管理和配置,而无需在 MyBatis 中手动配置连接信息。
属性 | 说明 |
---|---|
initial_context | 该属性主要用于在InitialContext中寻找上下文(即initialContext.lookup(initial_context))。该属性为可选属性,在忽略时,data_source属性会直接从InitialContext中寻找。 |
data_source | 该属性表示引用数据源对象位置的上下文路径。如果提供了initial_context配置,那么程序会在其返回的上下文中进行查找;如果没有提供,则直接在InitialContext中查找。 |
在示例工程中(In
src/main/resources/mybatis-config.xml
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14 <!-- 默认环境为dev-->
<environments default="dev">
<environment id="dev">
<!-- 设置使用JDBC事务管理 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
2.2.5 mappers
用于引入MyBatis映射文件。映射文件包含了POJO对象和数据表之间的映射信息,MyBatis通过核心配置文件中的
-
resource
:适用于类路径下的 XML 映射文件。 -
url
:适用于外部文件系统或网络路径的 XML 文件。 -
class
:适用于直接使用 Mapper 接口。 -
package
:适用于批量扫描 Mapper 接口,简化配置。
示例代码
1 | <mappers> |
在示例工程中(In
src/main/resources/mybatis-config.xml
)
1
2
3 <mappers>
<package name="site.icefox.javaeelearn.Mapper"/>
</mappers>
三 映射文件
3.1 namespace
-
用于区分不同的mapper,全局唯一。
-
绑定DAO接口,即面向接口编程。当namespace绑定某一接口之后,可以不用写该接口的实现类,MyBatis会通过接口的全限定名查找到对应的mapper配置来执行SQL语句,因此namespace的命名必须跟接口同名。
MyBatis通过
3.2 常用节点
属性 | 说明 |
---|---|
mapper | 映射文件的根元素,该元素只有一个namespace属性(命名空间)。 |
cache | 配置给定命名空间的缓存。 |
cache-ref | 从其他命名空间引用缓存配置。 |
resultMap | 描述数据库结果集和对象的对应关系。 |
sql | 可以重用的SQL块,也可以被其他语句使用。 |
insert | 用于映射插入语句。 |
delete | 用于映射删除语句。 |
update | 用于映射更新语句。 |
select | 用于映射查询语句。 |
3.2.1 select
<select>
元素用来映射查询语句,它可以从数据库中查询数据并返回。
常用属性如下
属性 | 说明 |
---|---|
id | 表示命名空间中 |
parameterType | 它是一个可选属性,用于指定SQL语句所需参数类的全限定名或者别名,其默认值是unset。 |
resultType | 用于指定执行这条SQL语句返回的全限定类名或别名。 |
resultMap | 表示外部resultMap的命名引用。resultMap和resultType不能同时使用。 |
flushCache | 用于指定是否需要MyBatis清空本地缓存和二级缓存。 |
useCache | 用于控制二级缓存的开启和关闭。 |
timeout | 用于设置超时时间,单位为秒。 |
fetchSize | 获取记录的总条数设定,默认值是unset。 |
statementType | 用于设置MyBatis预处理类。 |
resultSetType | 表示结果集的类型,它的默认值是unset。 |
在示例工程中 (In
src/main/resources/site/icefox/javaeelearn/Mapper/UsersMapper.xml
)
1
2
3
4 <!--select查询语句-->
<select id="getUserByUid" resultType="UsersEntity">
select * from d_mybiteslearn.t_users where uid = #{uid}
</select>
3.2.2 insert
-
元素用于映射插入语句,在执行完 元素中定义的SQL语句后,会返回插入记录的数量。
在示例工程中 (In
src/main/resources/site/icefox/javaeelearn/Mapper/UsersMapper.xml
)
1
2
3
4 <!-- 插入操作 -->
<insert id="addUser" parameterType="UsersEntity" keyProperty="uid" useGeneratedKeys="true">
insert into t_users (uid, uname, uage, usex) value (#uid, #uname, #uage, #usex)
</insert>
-
数据库获取主键值的方式
-
使用支持主键自动增长的数据库获取主键值
如果使用的数据库支持主键自动增长(如MySQL和SQL Server),那么可以通过keyProperty属性指定POJO类的某个属性接收主键返回值(通常会设置到id属性上),然后将useGeneratedKeys的属性值设置为true。
1
2
3
4<!-- 插入操作 -->
<insert id="addUser" parameterType="UsersEntity" keyProperty="uid" useGeneratedKeys="true">
insert into t_users (uid, uname, uage, usex) value (#uid, #uname, #uage, #usex)
</insert> -
使用不支持主键自动增长的数据库获取主键值
使用MyBatis提供的
元素来自定义主键。 在上述 元素的属性中,order属性可以被设置为BEFORE或AFTER。如果设置为BEFORE,那么它会首先执行 元素中的配置来设置主键,然后执行插入语句;如果设置为AFTER,那么它先执行插入语句,然后执行 元素中的配置内容。
-
3.2.3 update
在示例工程中(In
src/main/resources/site/icefox/javaeelearn/Mapper/UsersMapper.xml
)
1
2
3
4
5
6
7
8 <!-- 修改操作 -->
<update id="updateUser" parameterType="UsersEntity">
update t_users
set uname= #{uname},
uage = #{uage},
usex = #{usex}
where uid = #{uid}
</update>
3.2.4 delete
在示例工程中(In
src/main/resources/site/icefox/javaeelearn/Mapper/UsersMapper.xml
)
1
2
3
4 <!-- 删除操作 -->
<delete id="deleteUser" parameterType="Integer">
delete from t_users where uid=#{uid}
</delete>
属性 | 说明 |
---|---|
id | 表示命名空间中 |
parameterType | 它是一个可选属性,用于指定SQL语句所需参数类的全限定名或者别名,其默认值是unset。 |
flushCache | 用于指定是否需要MyBatis清空本地缓存和二级缓存。 |
timeout | 用于设置超时时间,单位为秒。 |
statementType | 用于设置MyBatis预处理类。 |
3.2.5 Sql
在一个映射文件中,通常需要定义多条SQL语句,这些SQL语句的组成可能有一部分是相同的(如多条select语句中都查询相同的id、username字段),如果每一个SQL语句都重写一遍相同的部分,势必会增加代码量。针对此问题,可以在映射文件中使用MyBatis所提供的
1 | <!--定义要查询的表 --> |
3.2.6 resultMap
默认情况下,MyBatis程序在运行时会自动将查询到的数据与需要返回的对象的属性进行匹配赋值(数据表中的列名与对象的属性名称完全一致才能匹配成功并赋值)。然而实际开发时,数据表中的列和需要返回的对象的属性可能不会完全一致,这种情况下MyBatis不会自动赋值,这时就需要使用
3.2.6.1 测试代码
书写如下代码用于测试
src/main/resources/site/icefox/javaeelearn/Mapper/StudentsMapper.xml
1 |
|
src/main/java/site/icefox/javaeelearn/Dao/StudentsDao.java
1 | package site.icefox.javaeelearn.Dao; |
src/main/avajjava/site/icefox/javaeelearn/Entity/StudentsEntity.java
1 | package site.icefox.javaeelearn.Entity; |
src/main/java/site/icefox/javaeelearn/Mapper/StudentsMapper.java
1 | package site.icefox.javaeelearn.Mapper; |
src/test/java/ResultMapTest.java
1 | import org.junit.Test; |
3.2.6.2 测试结果
1 | [StudentsEntity(id=1, name=张三, age=25), StudentsEntity(id=2, name=李四, age=21), StudentsEntity(id=3, name=王五, age=20)] |