目录
一、MyBatis概述
1.1框架(framework)
1.2三层架构
1.3JDBC的不足
1.4了解MyBatis
二、MyBatis入门程序
2.1resources目录
2.2开发步骤
2.3从XML中构建SqlSessionFactory
2.4mybatis中有两个主要的配置文件
2.5关于第一个程序的细节
2.6关于mybatis的事务管理机制(深度剖析)
2.7单元测试
2.8关于mybatis集成日志组件,让我们调试起来更加方便
2.9MyBatis⼯具类SqlSessionUtil的封装
三、使用MyBatis完成CRUD
3.1什么是CRUD
3.2insert
3.3delete
3.4update
3.5select查询单条记录
3.6select查询所有记录
3.7关于SQL Mapper的namespace
四、MyBatis核心配置文件详解
一、MyBatis概述
1.1框架(framework)
-
Java常用框架:
-
SSM三大框架:Spring+SpringMVC+MyBatis
-
SpringBoot
-
SpringCloud
-
-
框架其实就是对通用代码的封装,提前写好了一堆接口和类,我们可以在做项目的时候直接引用这些接口和类,基于这些现有的接口和类进行开发,可以大大提高开发效率。
-
框架一般都以jar包的形式存在。(jar包中有class文件以及各种配置文件等)
1.2三层架构
-
表现层(UI):直接跟前端交互(一是接收前端的ajax请求,二是返回json数据给前端)。
-
业务逻辑层(BLL):一使处理表现层转发过来的前端请求(具体业务),二是将持久化层获取的数据返回到表现层。
-
数据访问层(DAL):直接完成数据库的CRUD,并将获得的数据返回到上一层(也就是业务逻辑层)。
-
Java的持久层框架:
-
MyBatis
-
Hibernate(实现了JPA规范)
-
jOOQ
-
Guzz
-
Spring Data(实现了JPA规范)
-
Active JDBC
-
......
-
1.3JDBC的不足
-
SQL语句写死在Java程序中,不灵活。改SQL的话就要改Java代码。违背了开闭原则OCP。
-
给?传值是繁琐的,不能自动化。
-
将结果集封装成Java对象是繁琐的,不能自动化。
1.4了解MyBatis
-
MyBatis本质上就是对JDBC的封装,通过MyBatis完成CRUD。
-
MyBatis在三层架构中复制持久化层,属于持久层框架。
-
ORM:对象关系映射
-
O(Object):Java虚拟机中的Java对象。
-
R(Relational):关系型数据库。
-
M(Mapping):将Java虚拟机中的Java对象映射到数据库表中一行记录,或是将数据库表中一行记录映射成Java虚拟机中的一个Java对象。
-
-
-
MyBatis属于半自动化ORM模型,Hibernate属于全自动化的ORM框架。
-
MyBatis框架特点:
-
支持定制化SQL、存储过程、基本映射以及高级映射。
-
避免了几乎所有的JDBC代码中手动设置参数以及获取结果集。
-
支持XML开发,也支持注解式开发。(为了保证sql语句的灵活,所以mybatis大部分是采用XML方式开发)
-
将接口和Java的POJOs映射成数据库中的记录。
-
体积小好学:两个jar包,两个XML配置文件。
-
完全做到SQL解耦合。
-
提供了基本映射标签、高级映射标签、XML标签,支持动态SQL的编写。
-
......
-
二、MyBatis入门程序
2.1resources目录
放到这个目录中的一般都是资源文件、配置文件。
直接放到resources目录下的资源等同于放到了类的根路径下。
2.2开发步骤
-
打包方式jar
<!--打包方式--> <packaging>jar</packaging>
-
引入依赖:
-
mybatis依赖
-
mysql依赖
<dependencies> <!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.11</version> </dependency> <!--mysql驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency> </dependencies>
-
-
编写mybatis核心配置文件: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">
<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/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="030522"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--执行XxxMapper.xml文件的路径-->
<!--resources属性自动会从类的根路径下开始查找资源-->
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
-
编写XxxxMapper.xml文件
-
在这个文件中编写SQL语句,这个文件名和存放位置也不是固定的。
-
<?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">
<mapper namespace="abc">
<!--insert语句,id是这条sql语句的唯一标识,这个id就代表了这条sql语句-->
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,'1003','丰田霸道',30.0,'2020-10-10','燃油车')
</insert>
</mapper>
-
在mybatis-config.xml文件中指定XxxxMapper.xml文件的路径:
<mapper resource="CarMapper.xml"/>
-
注意:resource属性会自动从类的根路径下开始查找资源。
-
-
编写mybatis程序。(使用mybatis的类库,编写mybatis程序,连接数据库,做crud)
-
在mybatis当中,负责执行SQL语句的那个对象是SqlSession。
-
SqlSession是专门用来执行SQL语句的,是一个Java程序和数据库之间的一次会话。
-
要想先获取SqlSession对象,需要先获取SqlSessionFactory对象,通过SqlSessionFactory工厂来生产SqlSession对象。
-
要想获取SqlSessionFactory对象,需要先获取SqlSessionFactoryBuilder对象,通过SqlSessionFactoryBuilder对象的bulid方法,来获取一个SqlSessionFactory对象。
-
mybatis核心包括:SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession
-
SqlSessionFactoryBuilder--->SqlSessionFactory--->SqlSession
-
2.3从XML中构建SqlSessionFactory
在mybatis中有一个很重要的对象SqlSessionFactory,SqlSessionFactory对象的创建需要XML(配置文件)。
2.4mybatis中有两个主要的配置文件
-
mybatis-config.xml,这个是核心配置文件,主要配置连接数据库的信息等。(只要一个)
-
XxxxMapper.xml,这个文件是专门用来编写SQL语句的配置文件。(一个表对应一个)
2.5关于第一个程序的细节
-
mybatis中的SQL语句的结尾";"可以省略。
-
Resources.getResourceAsStream
-
以后凡是遇到resource这个单词,大部分情况下,这种加载资源的方式就是从类的根路径下开始加载(查找)。
-
优点:采用这种方式,从类路径当中加载资源,项目的移植性很强。例如:项目从windows移植到linux,代码不需要修改,因为这个资源文件一直都在类路径当中。
-
-
InputStream is = new FileInputStream("d:\\mybatis-config.xml");
-
采用这种方式也可以。
-
缺点:可移植性太差,程序不够健壮,当移植到其它系统当中,可能导致路径失效,还需要修改java代码中的路径,违背了OCP原则。
-
-
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
-
ClassLoader.getSystemClassLoader() 获取系统的类加载器。
-
系统的类加载器中有一个方法:getResourceAsStream,它就是从类路径当中加载资源的。
-
InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); 底层就是:InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
-
-
CarMapper.xml文件的名字和位置不是固定的。
-
<mapper resource="CarMapper.xml"/> resource属性:这种方式是从类路径当中加载资源的。
-
<mapper url="file:///d:/CarMapper.xml"/> url属性:这种方式是从绝对路径当中加载资源的。
-
2.6关于mybatis的事务管理机制(深度剖析)
-
在mybtais-config.xml文件中,可以通过<transactionManager type="JDBC">的配置进行mybatis事务的管理。
-
type属性的值包含两个(不包含大小写):JDBC、MANAGED
-
在mybatis中提供了两种事务管理机制:JDBC事务管理机制、MANAGED事务管理机制
-
JDBC事务管理机制
-
mybatis框架自己管理事务,自己采用原生的JDBC代码去管理事务。
-
conn.setAutoCommit(false);//开启事务 //...业务处理... conn.commit();//手动提交事务
-
使用JDBC事务管理器的话,底层创建的事务管理器对象:JdbcTransaction
-
SqlSession sqlSession = sqlSessionFactory.openSession(true); 表示没有开启事务,因为这种方式不会执行:conn.setAutoCommit(false); 在JDBC事务中,没有执行conn.setAutoCommit(false),那么autoCommit就是true。 如果autoCommit是true,就表示没有开启事务,只要执行任意一条DML语句就提交一次。
-
-
MANAGED事务管理器
-
mybatis不再负责事务的管理,事务的管理交给其它容器类执行,例如:spring。
-
对于目前只有mybatis的情况下,如果配置MANAGED,那么事务就没有人管,没有人管说明事务根本没有开启。
-
-
重点:只要autoCommit是true,就表示没有开启事务。只要autoCommit是false,就表示开启了事务。
2.7单元测试
package com.hhb.junit.service;
/**
* 数学业务类
*/
public class MathService {
/**
* 求和的业务方法
*
* @param a
* @param b
* @return
*/
public int sum(int a, int b) {
return a + b;
}
/**
* 相减的业务方法
*
* @param a
* @param b
* @return
*/
public int sub(int a, int b) {
return a - b;
}
}
package com.hhb.junit.service;
import org.junit.Assert;
import org.junit.Test;
/**
* 单元测试类
*/
public class MathServiceTest {//名字规范:类名+Test
//单元测试方法一般一个业务方法对应一个测试方法
//测试方法规范:public void testXxxx(){}
//测试方法的方法名:以test开始,testXxx
//@Test注解非常重要,被这个注解标注的方法就是一个单元测试方法
@Test
public void testSum() {
//单元测试中有两个重要的概念
//一个是实际值(被测试的业务方法的真正执行结果)
//一个是期望值(执行了这个业务方法之后,期望的执行结果是多少)
MathService mathService = new MathService();
//获取实际值
int actual = mathService.sum(1, 2);
//期望值
int expected = 3;
//加断言进行测试
Assert.assertEquals(expected, actual);
}
@Test
public void testSub() {
int actual = new MathService().sub(10, 5);
int expected = 5;
Assert.assertEquals(expected, actual);
}
}
2.8关于mybatis集成日志组件,让我们调试起来更加方便
-
mybatis常见的集成的日志组件有哪些?
-
SLF4J(沙拉风):沙拉风是一个日志标准,其中有一个框架叫做logback,它实现了沙拉风规范。
-
LOG4J
-
LOG4J2
-
STDOUT_LOGGING
-
...
-
注意:log4j log4j2 logback都是同一个作者开发的。
-
-
STDOUT_LOGGING是标准日志,mybatis已经实现了这种标准日志,mybatis框架本身已经实现了这种标准,只要开启即可。
-
在mybatis-config.xml文件中使用settings标签进行配置开启
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
-
这个标签在编写的时候要注意,它应该出现在environments标签之前。
-
这种实现是可以的,可以看到一些信息,比如:连接对象什么时候创建、什么时候关闭、sql语句是怎样的。但是没有详细的日期、线程名称等,如果想要使用更加丰富的配置,可以集成第三方的log组件。
-
-
集成logback日志框架
-
logback日志框架实现了slf4j规范
-
第一步:引入logback的依赖。
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency>
-
第二步:引入logback所必须的xml配置文件
-
这个配置文件的名字必须叫做:logback.xml或者logback-test.xml,不能是其它的名字。
-
这个配置文件必须放到类的根路径下,不能在其它位置。
-
主要配置日志输出相关的级别以及日志具体的格式。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>[%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!--mybatis log configure--> <logger name="com.apache.ibatis" level="TRACE"/> <logger name="java.sql.Connection" level="DEBUG"/> <logger name="java.sql.Statement" level="DEBUG"/> <logger name="java.sql.PreparedStatement" level="DEBUG"/> <!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="FILE"/> </root> </configuration>
-
-
2.9MyBatis⼯具类SqlSessionUtil的封装
-
每一次获取SqlSession对象代码太繁琐,封装一个工具类
package com.hhb.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
/**
* MyBatis工具类
*/
public class SqlSessionUtil {
//工具类的构造方法一般都是私有话的
//工具类中所有的方法都是静态的,直接采用类名即可调用,不需要new对象
//为了防止new对象,构造方法私有化
private SqlSessionUtil() {
}
private static SqlSessionFactory sqlSessionFactory;
//类加载时执行
//SqlSessionUtil工具类在进行第一次加载的时候,解析mybatis-config.xml文件,创建SqlSessionFactory对象。
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取会话对象
*/
public static SqlSession openSession() {
return sqlSessionFactory.openSession();
}
}
-
测试工具类
@Test
public void testInsertCar(){
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执⾏SQL
int count = sqlSession.insert("insertCar");
System.out.println("插⼊了⼏条记录:" + count);
sqlSession.close();
}
三、使用MyBatis完成CRUD
3.1什么是CRUD
-
C:Create增
-
R:Retrieve查(检索)
-
U:Update改
-
D:Delete删
3.2insert
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,'1003','丰田霸道',30.0,'2000-10-11','燃油车');
</insert>
-
这样写的问题是:值显然写死在配置文件中的,这个在实际开发中是不存在的,一定是前端的form表单提交过来数据,然后将值传给sql语句。
-
在JDBC中占位符采用的是?,在mybatis中用到是#{},不能使用?占位符。
-
java程序中使用Map可以给SQL语句的占位符传值,一般map集合的key起名的时候要见名知意。
-
#{写map集合的key,如果key不存在,获取的是null}
Map<String,Object> map = new HashMap<>();
map.put("carNum", "1111");
map.put("brand", "比亚迪汉2");
map.put("guidePrice", 10.0);
map.put("produceTime", "2020-11-11");
map.put("carType", "电车");
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType});
Java程序中使用POJO类给SQL语句的占位符传值
-
Car car = new Car(null,"3333","比亚迪秦",30.0,"2020-11-13","新能源");
-
注意:占位符#{},大括号里面写pojo类的属性名
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
-
将sql语句换为这种:
-
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{xyz},#{brand},#{guidePrice},#{produceTime},#{carType})
-
会出现的问题:
There is no getter for property named 'xyz' in 'class com.hhb.pojo.Car'
,mybatis去找Car类中的getXyz()方法去了,没有找到就报错。 -
解决方法:在Car类提供一个getXyz()方法,这样问题就解决了。
-
-
通过测试得出结论:严格意义上说,如果POJO对象传递值的话,#{}这个大括号中写的是get方法的方法名去掉get,然后将剩下的单词首字母小写。例如:getUsername()-->#{username}
3.3delete
-
需求:根据id删除数据
-
实现:
-
注意:如果占位符只有一个,那么#{}的大括号里可以随意,但最好是见名知意。
int count = sqlSession.delete("deleteById", 59); <delete id="deleteById"> delete from t_car where id = #{fdsfd} </delete>
-
3.4update
-
需求:根据id修改某条记录
-
实现:
<update id="updateById"> update t_car set car_num=#{carNum}, brand=#{brand}, guide_price=#{guidePrice}, produce_time=#{produceTime}, car_type=#{carType} where id = #{id} </update> Car car = new Car(5L, "9999", "奥迪A7", 60.50, "2021-05-06", "燃油车"); SqlSession sqlSession = SqlSessionUtil.openSession(); int count = sqlSession.update("updateById", car); System.out.println(count); sqlSession.commit(); sqlSession.close();
3.5select查询单条记录
-
需求:根据id查询单条记录
-
实现:
<select id="selectById" resultType="com.hhb.pojo.Car"> select * from t_car where id = #{id} </select> Object car = sqlSession.selectOne("selectById", 1);
-
需要特别注意的是:select标签中resultType属性,这个属性告诉mybatis,查询结果集封装成什么类型的java对象。resultType通常写的是全限定类名。
-
输出结果不完整:
Car{id=1, carNum='null', brand='宝马520Li', guidePrice=null, produceTime='null', carType='null'}
-
null的原因是:car_num、guide_price、produce_time、car_type这是查询结果的列名。这些列名和Car类中的属性名对不上,Car类的属性名:carNum、guidePrice、produceTime、carType。
-
解决方案:select语句查询的时候,查询结果集的列名是可以使用as关键字起别名的。
<select id="selectById" 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 where id = #{id} </select>
-
3.6select查询所有记录
-
需求:查询所有记录
-
实现:
<select id="selectAll" resultType="com.hhb.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> @Test public void testSelectAll() { SqlSession sqlSession = SqlSessionUtil.openSession(); //List<Object> cars = sqlSession.selectList("selectAll"); List<Car> cars = sqlSession.selectList("selectAll"); cars.forEach(car -> System.out.println(car)); sqlSession.close(); }
-
注意:resultType还是指定要封装的结果集的类型。不是指定list类型,是指定list集合中元素的类型。selectList方法:mybatis通过这个方法就可以得知你需要一个List集合,它会自动给你返回一个List集合。
-
3.7关于SQL Mapper的namespace
-
在sql mapper.xml文件当中有一个namespace,这个属性是用来指定命名空间的,防止id重复。
-
在xml文件中:
<mapper namespace="abcdef">
<select id="selectAll" resultType="com.hhb.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>
-
在java程序中:
@Test
public void testNamespace() {
SqlSession sqlSession = SqlSessionUtil.openSession();
//正确完整的写法:namespace.id
List<Car> cars = sqlSession.selectList("abcdef.selectAll");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
四、MyBatis核心配置文件详解
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">
<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/po
wernode"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="CarMapper.xml"/>
<mapper resource="CarMapper2.xml"/>
</mappers>
</configuration>
-
configuration:根标签,表示配置信息
-
environments:环境(多个),以"s"结尾表示复数,也就是说mybatis的环境可以配置多个数据源。
-
default属性:表示默认使用的是哪个环境,default后面填写的是environment的id。default的值只需要和environment的id值一致即可。
-
-
environment:具体的环境配置(主要包括:事务管理器的配置+数据源的配置)
-
id:给当前环境一个唯一的标识,该标识用在environments的default后面,用来指定默认的环境选择。
-
-
transactionManager:配置事务管理器
-
type属性:指定事务管理器具体使用什么方式,可选值有两个
-
JDBC:使用JDBC原生的事务管理机制。底层原理:事务开启。
conn.setAutoCommit(false); ...处理业务...事务提交conn.commit();
-
MANAGED:交给其它容器来管理事务,比如WebLogic、JBOSS等。如果没有管理事务的容器,则没有事务。没有事务的含义:只要执行一条DML语句,则提交一次。
-
-
-
dataSource:指定数据源
-
type属性:用来指定具体使用的数据库连接池的策略,可选值包含三个
-
UNPOOLED:采用传统的获取连接的方式,虽然也实现了Javax.sql.DataSource接口,但是没有使用池的思想。
-
property可以是:
-
driver
-
url
-
username
-
password
-
defaultTransactionIsolationLevel 默认的连接事务隔离级别。
-
defaultNetworkTimeout 等待数据库操作完成的默认网络超时时间(单位:毫秒)
-
-
-
POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现。
-
property可以是(除了包含UNPOOLED中之外):
-
poolMaximumActiveConnections 在任意时间内可存在的活动(正在使用)连接数量,默认值:10
-
poolMaximumIdleConnections 任意时间可能存在的空闲连接数。
-
......
-
-
-
JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。如果不是web或者maven的war工程,JNDI是不能使用的。
-
property可以是(最多只包含以下两个属性):
-
initial_context 这个属性用来在 InitialContext 中寻找上下文
-
data_source 这是引⽤数据源实例位置的上下⽂路径。
-
-
-
-
-
mappers:在mappers标签中可以配置多个sql映射文件的路径。
-
mapper:配置某个sql映射文件的路径
-
resource属性:使用相对于类路径的资源引用方式
-
url属性:使用完全限定资源定位符(URL)方式
-
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">
<configuration>
<!--java.util.Properties类,是一个map集合,key和value都是String类型-->
<!--在properties标签中可以配置很多属性-->
<!--<properties>
<property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="030522"/>
</properties>-->
<!--resource,一定是从类路径下开始查找资源-->
<properties resource="jdbc.properties" />
<!--从绝对路径当中加载资源-->
<!--<properties resource="file:///d:/jdbc.properties"/>-->
<!--default表示默认使用的环境-->
<environments default="mybatis">
<!--其中的一个环境连接的数据库是mybatis-->
<!--一般一个数据库会对应一个SqlSessionFactory对象-->
<!--一个环境environment会对应一个SqlSessionFactory对象-->
<environment id="mybatis">
<!--transactionManager标签:
1.作用:配置事务管理器,指定mybatis具体使用什么方式来管理事务
2.type属性有两个值:
JDBC:使用原生的JDBC代码来管理事务
conn.setAutoCommit(false);
...
conn.commit();
MANAGED:mybatis不再负责事务的管理,将事务管理交给其它的JEE(Java EE)容器来管理,例如:spring
3.不区分大小写,只能二选一,不能写其它的值
4.再mybatis中提供了一个事务管理器接口:transaction
该接口下有两个实现类:
JdbcTransaction
ManagedTransaction
如果type="JDBC",那么底层实现JdbcTransaction对象
如果type="MANAGED",那么底层实现ManagedTransaction对象
-->
<transactionManager type="JDBC"/>
<!--
dataSource配置:
1.dataSource被称为数据源
2.dataSource作用:为程序提供Connection对象。(只要给程序员提供Connection对象的,都叫做数据源)
3.数据源实际上是一套规范,JDK中有这套规范:javax.sql.DataSource
4.我们自己也可以编写数据源组件,只要实现javax.sql.DataSource接口中的所有方法就行了。
5.常见的数据源组件(数据库连接池):
druid、c3p0、dbcp...
6.type属性用来指定数据源的类型,就是指定具体使用什么方式来获取Connection对象
type属性有三个值,必须是三选一
UNPOOLED:不使用数据库连接池技术,每一次请求过来之后,都是创建新的Connection对象。
POOLED:使用mybatis自己实现的数据库连接池
JNDI:集成其它第三方的数据库连接池
JNDI是一套规范,大部分的web容器都实现了JNDI规范,例如:Tomcat、Jetty、WebLogic、WebSphere
...这些服务器(容器)都实现了JNDI规范
JNDI是java命名目录接口,Tomcat容器实现了这个规范
<dataSource type="JNDI">
<property name="initial_context" value="..."/>
<property name="data_source" value="...."/>
</dataSource>
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--提醒:正常使用连接池的话,池中有很多参数是需要设置的,设置好参数,可以让连接池发挥的更好-->
<!--具体连接池当中的参数如何配置呢?需要反复的根据当前业务情况进行测试-->
<!--poolMaximumActiveConnections:连接池当中最多的正在使用的连接对象的数量上限,最多有多少个连接可以活动,默认值是10-->
<property name="poolMaximumActiveConnections" value="10"/>
<!--每隔2秒打印日志,并且尝试获取连接对象-->
<property name="poolTimeToWait" value="2000"/>
<!--强行让某个连接空闲,超时时间的设置-->
<property name="poolMaximumCheckoutTime" value="10000"/>
<!--最多的空闲数量-->
<property name="poolMaximumIdleConnections" value="5"/>
</dataSource>
</environment>
<!--这个mybatis的另一个环境,也就是连接的数据库是另一个数据库mybatis02-->
<environment id="mybatis02">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis02"/>
<property name="username" value="root"/>
<property name="password" value="030522"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
configTest.java
package com.hhb.test;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
public class ConfigTest {
@Test
public void testDataSource() throws IOException {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//sqlSessionFactory对象:一个数据一个,不要频繁创建该对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
/*//通过sqlSessionFactory对象可以频繁开启多个对话
//会话一
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("car.insertCar");
sqlSession.commit();
sqlSession.close();
//会话二
SqlSession sqlSession1 = sqlSessionFactory.openSession();
sqlSession1.insert("car.insertCar");
sqlSession1.commit();
sqlSession1.close();*/
for (int i=1;i<=4;i++){
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("car.insertCar");
}
}
@Test
public void testEnvironment() throws Exception {
//获取SqlSessionFactory对象(采用默认的方式获取)
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("car.insertCar");
sqlSession.commit();
sqlSession.close();
//通过环境id来使用指定的环境
SqlSessionFactory sqlSessionFactory1 = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis02");
SqlSession sqlSession1 = sqlSessionFactory1.openSession();
int insert = sqlSession1.insert("car.insertCar");
sqlSession1.commit();
sqlSession1.close();
}
}