MyBatis中的核心配置文件
mybatis-config.xml
核心配置文件,主要配置连接数据库的信息等(一个)
核心配置文件的加载方式
关于XMl文件的dtd约束
dtd约束
: 用来约束文件中可以出现的标签及其子标签标签,标签中出现的属性及属性值,各种标签之间出现的顺序等等
- 一般通过查看idea的报错提示信息确定
mybatis-config.xml
⽂件中标签的约束信息
<?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">
核心配置文件的加载方式
MyBatis中提供了⼀个org.apache.ibatis.io.Resources类
可以从类路径当中加载资源文件 , 我们通常使用它来获取输入流InputStream
- Resources类的
getResourceAsStream
方法底层会调用系统类加载器的getResourceAsStream
方法从类路径中加载资源
new FileInputStream("d:\\mybatis-config.xml")
: 表示从绝对路径中加载资源文件
- 以绝对路径的方式加载核心配置文件可移植性太差,当项目从windows移植到linux时需要修改代码违背了OCP原则
ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml")
: 从类路径当中加载资源文件即使切换系统也不需要修改代码
方法名 | 迷描述 |
---|---|
ClassLoader.getSystemClassLoader() | 调用ClassLoader方法获取系统的类加载器 |
getResourceAsStream | 系统类加载器从类路径中加载资源文件的方法 大部分带有 resourcexxx,classpathxxx 的方法都是从类的根路径下开始查找资源并加载 |
// 从绝对路径中加载资源文件
InputStream is = new FileInputStream("d:\\mybatis-config.xml");
// 利用类加载器加载资源
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
// ibatis包下的工具类Resources.getResourceAsStream方法默认从类的根路径下开始查找资源
InputStream is = Resources.getResourceAsStream("mybatis-config.xml")
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
核心配置文件的基本标签
configuration(根标签)
configuration(根标签)
核心配置文件中最大的标签, 表示配置信息
properties标签(配置信息)
第一种方式: 在properties标签
中使用子标签property的name和value属性
配置连接数据库的url,用户名,密码
等信息,然后在数据源中通过${key}
取值
<properties>
<!--<property name="属性名" value="属性值"/>-->
<property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/powernode"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--${key}使⽤-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
第二种方式: 使用properties标签的resource属性或url属性
引入外部的属性配置文件,然后在数据源中使用${key}
取值
#java.util.Properties类是一个Map集合,key和value都是String类型
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/powernode
jdbc.username=root
jdbc.password=root
<!--resource属性,一定是从类路径下开始加载属性配置文件-->
<properties resource="jdbc.properties" />
<!--从绝对路径当中加载资源文件 ,格式file:///路径-->
<properties url="file:///d:/jdbc.properties" />
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--${key}使⽤-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
typeAliases标签(别名机制)
若select标签的resultType属性
指定的查询结果集要封装的对象类型名字太⻓可以使⽤typeAliases标签的别名机制,但是namespqnce属性不能使用别名机制
typeAlias子标签
: 单独的给每一个类起别名package子标签
: 若⼀个包下的每个类都需要起别名会导致typeAlias标签较多, 此时可以指定给一个包下的所有类起别名
typeAlias标签
: 父标签typeAliases标签的要放在MyBatis核心配置文件中的setting标签
后面不然会报错
type属性
: 指定给哪个类起别名alias属性
: 指定类的别名, 省略alias属性后默认以type属性指定类的简类名作为别名并且不区分⼤⼩写
<typeAliases>
<typeAlias type="com.powernode.mybatis.pojo.Car" alias="Car"/>
<!--com.powernode.mybatis.pojo.Car的别名就是Car/car/cAR/cAr-->
<typeAlias type="com.powernode.mybatis.pojo.Car"/>
</typeAliases>
package标签
: 指定给一个包下的所有类都自动起别名
name属性
: 指定给哪个包下的所有类起别名 ,默认别名是类的简类名且不区分大小写
<typeAliases>
<!--给包下的所有的类全部自动起别名-->
<package name="com.powernode.mybatis.pojo"/>
</typeAliases>
<!--不使用别名机制-->
<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
select
id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
from
t_car
</select>
</mapper>
<!--使用别名机制-->
<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
<select id="selectAll" resultType="CAR">
select
id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
from
t_car
</select>
</mapper>
MyBatis内置的Java类型别名
MyBatis内置的Java类型的别名都是不区分大小写的
,另外为了防止与原始类型的命名重复还采取了特殊的命名风格具体参考mybatis中文手册
基本数据类型
: 别名是在其前面加个下划线,如double类型的别名为_double包装数据类型
: 别名是其对应的基本数据类型名引用数据类型
: 别名是类型名首字母小写
映射的类型 | 别名 |
---|---|
char | _ char/_ character (since 3.5.10) |
int | _ int/_integer |
String | string |
Integer | int/integer |
BigDecimal | bigdecimal/decimal |
Date | date |
Object | object |
Map/HashMap | map/hashmap |
mappers(引入SQL映射文件)
mappers标签中可以配置多个mappr标签用来引入多个SQL映射⽂件
,一共有四种引入SQL映射⽂件的方式
方式 | 描述 |
---|---|
resource属性 | 从类路径中加载SQL映射文件 Maven工程中的java目录和resources目录都表示类的根路径,项目打包后它们里面的文件最终都会放在target/classes目录下 |
url属性 | 从指定的绝对路径中加载SQL映射文件 |
class属性 | 将提供的mapper接口的全限定接口名转化为对应的目录结构然后去引入对应的SQL映射文件 这种方式需要将SQl映射文件XxxMapper.xml和XxxMapper接口放在在同⼀个目录下且文件名字⼀致 在IDEA的resources目录下新建多重目录必须写成 com/powernode/mybatis/mapper ,使用. 的方式创建的是一级目录 |
package标签(实际开发中常用) | 将一个包下所有mapper接口的全限定接口名都转化为对应的目录结构然后去引入对应的SQL映射文件 |
第⼀种resource属性引入
: 从类的根路径下加载SQL映射文件
<mappers>
<!--引入类的根路径下的test包下的CarMapper.xml文件-->
<mapper resource="test/CarMapper.xml"/>
</mappers>
第二种url属性引入
:从指定的绝对路径的位置加载SQL映射文件(使用极少移植性太差)
<!--引入d盘下的CarMapper.xml⽂件-->
<mappers>
<mapper url="file:///d:/CarMapper.xml"/>
</mappers>
第三种class属性引入
: 将指定mapper接口的全限定接口名转化为对应的目录然后去引入对应的SQL映射文件
- 指定
com.powernode.mybatis.mapper.CarMapper
接口, MyBatis框架底层自动会去`com/powernode/mybatis/mapper目录下查找CarMapper.xml文件
<!--使⽤映射器接⼝实现类的完全限定类名-->
<mappers>
<!--mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件-->
<mapper class="com.powernode.mybatis.mapper.CarMapper "/>
</mappers>
第四种方式package标签引入
: 将包下所有mapper接口的全限定接口名都转化为目录然后去引入对应的SQL映射文件
<!--将包内的映射器接⼝实现全部注册为映射器-->
<mappers>
<package name="com.powernode.mybatis.mapper"/>
</mappers>
environments(多环境标签)
环境的Id
environments(所有环境的配置)
: MyBatis中的环境可以配置多个,用来指定多个数据源
default属性
: 指定创建SqlSessionFactory对象
时具体使用的一个环境
environment(某个环境配置)
: 主要包括事务管理器的配置
和数据源的配置
Id属性
: 当前环境的唯⼀标识,Id名可以随意但一般起名为连接的数据库名
<configuration>
<!--默认使用环境1即连接的数据库是DB1-->
<environments default="DB1">
<!--环境1(连接的数据库是DB1)-->
<environment id="DB1">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/DB1"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--环境2(连接的数据库是DB2)-->
<environment id="DB2">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/DB2"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
一个环境对应一个数据库也对应一个SqlSessionFactory对象
, 使用不同的环境表示连接不同的数据库
方法名 | 功能 |
---|---|
build(Resources.getResourceAsStream(“核心配置文件”)) | 使用默认的环境创建SqlSessionFactory对象 |
build(Resources.getResourceAsStream(“核心配置文件”,“环境Id”)) | 指定创建SqlSessionFactory对象的环境 |
@Test
public void testEnvironment() throws Exception {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 使用默认的环境创建SqlSessionFactory,将来创建的会话连接的就是默认的数据库
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
// 创建SqlSession对象执行SQL语句
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("car.insertCar");
sqlSession.commit();
sqlSession.close();
// 指定创建SqlSessionFactory的环境,将来创建的会话连接的就是指定的数据库
SqlSessionFactory sqlSessionFactory1 = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml","DB2"));
// 创建SqlSession对象执行SQL语句
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession1.insert("car.insertCar");
sqlSession1.commit();
sqlSession1.close();
}
transactionManage事务管理标签
标签的type属性
transactionManage标签的type属性
:指定MyBatis管理事务的方式,type属性值包括JDBC和MANAGED
并且不区分大小写
MyBatisatis提供了一个Transaction
事务管理器接口,该接口下有JdbcTransaction
和ManagedTransaction
两个实现类
事务管理的方式 | 描述 |
---|---|
type=“JDBC” | 使⽤JDBC原⽣的事务管理机制管理事务,底层会创建事务管理器对象JdbcTransaction对象 |
type=“MANAGED” | 使用其它容器来管理事务,底层会创建事务管理器对象ManagedTransaction对象 |
JDBC事务管理器
type="JDBC"
表示MyBatis框架使⽤JDBC原⽣的事务管理机制管理事务,底层会创建事务管理器对象JdbcTransaction对象
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisDB"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<mappers>
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
// 底层默认执行JDBC原生的connection.setAutoCommit(false)表示关闭自动提交即开启事务
SqlSession sqlSession = sqlSessionFactory.openSession()
// 执行完增删改操作后需要执行手动提交事务,底层默认执行JDBC原生的connection.commit()
sqlSession.commit()
// 底层代码执行JDBC原生的connection.setAutoCommit(true)表示开启自动提交即关闭事务
SqlSession sqlSession = sqlSessionFactory.openSession(true)
// 只要执行任意一条DML语句就会自动提交一次,不需要手动提交
MANAGED事务管理器
type="MANAGED"
表示MyBatis框架不再负责事务的管理,交给WebLogic、JBOSS、Spring
等其它容器来管理事务
- 如果配置为MANAGED但又没有对应的容器管理事务时相当于没有开启事务, 那么此时只要执⾏⼀条DML语句则自动提交⼀次
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="MANAGED"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisDB"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<mappers>
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
// 没人管理事务相当于没有开启事务, 此时只要执⾏⼀条DML语句则自动提交⼀次
SqlSession sqlSession = sqlSessionFactory.openSession()
sqlSession.commit()
dataSource数据源标签
标签的type属性
数据源实际上是JDK规定的一套规范接口javax.sql.DataSource
,只要实现这个接口当中所有的方法相当于创建了一个数据源组件(数据库连接池)
常见的数据源组件(druid(德鲁伊),c3p0,dbcp)
: 每种数据库连接池都有自己获取Connection连接对象的方式- 使用了数据源后,每一次请求都是从池中取连接对象,关闭会话也只是把连接对象放回池中并不是真正的关闭
dataSource标签的type属性
: 设置提供Connection连接对象的数据库连接池,不同的数据源具体配置的属性会不同参考mybatis中文手册
数据源 | 描述 |
---|---|
type="UNPOOLED | 不使用数据库连接池技术, 而是采⽤传统的方式获取连接对象 |
type=“JNDI” | 采用对接JNDI服务器中的数据库连接池,如dbcp,c3p0,druid(德鲁伊)等第三⽅连接池 |
type=“POOLED” | 使用MyBatis框架自己实现了javax.sql.DataSource接口的数据库连接池 |
UNPOOLED(无连接池)
type="UNPOOLED"
表示不使用数据库连接池技术, 而是采⽤传统的方式获取连接对象
- 虽然也实现
Javax.sql.DataSource接口
但是并没有使⽤池的思想, 每一次请求过来之后都是创建新的Connection对象
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisDB"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<mappers>
<mapper resource="..."/>
</mappers>
</configuration>
测试不使用连接池
的效果
@Test
public void testDataSource() throws Exception{
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// sqlSessionFactory对象一个数据库一个,不要频繁创建该对象
// sqlSessionFactory对象可以开启多个会话,,一个线程对应一个会话
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
// 会话1
SqlSession sqlSession1 = sqlSessionFactory.openSession();
sqlSession1.insert("car.insertCar");
sqlSession1.commit();
// 关闭会话
sqlSession1.close();
// 会话2
SqlSession sqlSession2 = sqlSessionFactory.openSession();
sqlSession2.insert("car.insertCar");
sqlSession2.commit();
sqlSession2.close();
}
JNDI(第三方)
type="JNDI"
表示采用对接JNDI服务器中的数据库连接池,从而使⽤dbcp,c3p0,druid(德鲁伊)等第三⽅连接池的接⼝
-
JNDI是一套java命名目录规范接口
: 只有web⼯程才可以使用JNDI技术,大部分的web容器如Tomcat,Jetty等服务器都实现了这套规范 -
使用方式
: 先将第三方的连接池配到服务器上,然后采⽤服务器提供的JNDI技术来获取第三方实现的DataSource对象
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="JNDI">
<property name="initial_context" value="..."/>
<property name="data_source" value="..."/>
</dataSource>
</environment>
<mappers>
<mapper resource=.../>
</mappers>
</configuration>
POOLED(内置连接池)
type="POOLED"
表示使用MyBatis框架自己的实现了javax.sql.DataSource接口
的数据库连接池
配置MyBatis自己实现的数据源的参数
:配置时需要根据系统的实际并发情况,来合理调整连接池的最⼤连接数以及最多空闲数量 ,充分发挥数据库连接池的性能
属性名 | 功能描述 |
---|---|
poolMaximumActiveConnections 最⼤的活动的连接数量, 默认值10 | 如有10个请求正在使⽤这10个连接, 第11个请求只能等待空闲连接 |
poolMaximumIdleConnections 最⼤的空闲连接数量,默认值5 | 如已经有了5个空闲连接,当第6个连接要空闲下来时,连接池会真正关闭该连接对象来减少数据库开销 |
poolMaximumCheckoutTime 连接对象强⾏回归池的时间,默认值20秒 | 如果开启的某个连接对象超过规定时间的设置, 强行让它空闲即宣布它过期了,让正在等待的用户去获取 |
poolTimeToWait 当⽆法获取到空闲连接时,默认每隔20秒打印⼀次⽇志,配置时长单位是毫秒 | 如果获取连接花费了相当⻓的时间,连接池会打印状态⽇志并重新尝试获取⼀个连接对象,避免在误配置的情况下⼀直失败且不打印⽇志傻等 |
<environments default="mybatisDB">
<environment id="mybatisDB">
<transactionManager type="JDBC"/>
<!--正常使用连接池的话,需要反复的根据当前业务情况进行测试,设置好池中的参数可以让连接池发挥的更好-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!--规定连接池当中最多的正在使用的连接对象的数量上限-->
<property name="poolMaximumActiveConnections" value="10"/>
<!--设置每隔2秒打印日志-->
<property name="poolTimeToWait" value="2000"/>
<!--如果开启的某个连接对象超过规定时间的设置, 强行让它空闲即宣布它过期了,让正在等待的用户去获取-->
<property name="poolMaximumCheckoutTime" value="10000"/>
<!--如果此时连接池中有6个空闲的连接对象,那么连接池会真正关闭空闲的连接对象-->
<property name="poolMaximumIdleConnections" value="5"/>
</dataSource>
</environment>
</environments>
测试使用MyBatis框架自己的实现的数据库连接池
的效果
@Test
public void testDataSource() throws Exception{
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// sqlSessionFactory对象一个数据库一个,不要频繁创建该对象
// sqlSessionFactory对象可以开启多个会话,,一个线程对应一个会话
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
// 不要关闭连接对象,当超出了最大连接数要想再获取连接对象就需要排队等待
for (int i = 0; i < 10; i++) {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("car.insertCar");
}
}