一、MyBatis Configuration XML
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 configuration(配置)标签下主要有如下配置,配置的顺序要严格遵循列出的顺序
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
工程搭建
新建maven工程mybatis-config-xml,引入依赖
代码语言:javascript复制<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
增加entity包,新增Employee实体类
代码语言:javascript复制@Data
public class Employee {
private Integer id;
private String empName;
private String email;
private Integer gender;
}
增加dao包,新增EmployeeDao接口
代码语言:javascript复制public interface EmployeeDao {
Employee getEmpById(Integer id);
int updateEmployee(Employee employee);
boolean deleteEmployee(Integer id);
int insertEmployee(Employee employee);
}
在resource目录下增加全局配置文件mybatis-config.xml
代码语言:javascript复制<?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="dev">
<!--配置环境,不同的环境不同的id名字-->
<environment id="dev">
<!-- 采用JDBC方式对数据库事务进行commit/rollback -->
<transactionManager type="JDBC"></transactionManager>
<!--采用连接池方式管理数据库连接-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers/employee.xml"/>
</mappers>
</configuration>
增加mappers文件夹,在其中增加employee.xml
代码语言:javascript复制<?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="com.citi.dao.EmployeeDao">
<!--参数类型不用写-->
<select id="getEmpById" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{id}
</select>
<!--增删改不用写返回值类型,增删改返回的是影响了多少行,MyBatis自动判断
如果是boolean,影响0行自动封装为false,否则为true,
参数类型也不用写
#{属性名}-->
<update id="updateEmployee" parameterType="com.citi.entity.Employee">
UPDATE t_employee
SET empname = #{empName},
gender = #{gender},
email = #{email}
WHERE id = #{id}
</update>
<delete id="deleteEmployee">
DELETE FROM t_employee WHERE id = #{id}
</delete>
<insert id="insertEmployee" useGeneratedKeys="true" parameterType="com.citi.entity.Employee">
INSERT INTO t_employee(empname,gender,email) values (#{empName},#{gender},#{email})
</insert>
</mapper>
在resource目录下增加日志配置
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread] %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--
日志输出级别(优先级高到低):
error: 错误 - 系统的故障日志
warn: 警告 - 存在风险或使用不当的日志
info: 一般性消息
debug: 程序内部用于调试信息
trace: 程序运行的跟踪信息
-->
<root level="debug">
<appender-ref ref="console"/>
</root>
</configuration>
新增EmployeeDaoTest测试类
代码语言:javascript复制public class EmployeeDaoTest {
SqlSessionFactory sqlSessionFactory = null;
SqlSession openSession = null;
@Before
public void setUp() throws Exception {
//1、根据全局配置文件创建出一个SqlSessionFactory
//SqlSessionFactory:是SqlSession工厂,负责创建SqlSession对象;
//SqlSession:sql会话(代表和数据库的一次会话);
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
openSession = sqlSessionFactory.openSession();
}
@Test
public void getEmpById() throws Exception{
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Employee employee = employeeDao.getEmpById(1);
System.out.println(employee);
}
@Test
public void updateEmployee() {
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Employee updateEmployee = new Employee();
updateEmployee.setId(1);
updateEmployee.setEmpName("Tony Stark");
updateEmployee.setEmail("stark@stark-industry.com");
updateEmployee.setGender(0);
employeeDao.updateEmployee(updateEmployee);
Employee employee = employeeDao.getEmpById(1);
System.out.println(employee);
}
@Test
public void deleteEmployee() {
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
System.out.println(employeeDao.getEmpById(6));
boolean isDelete = employeeDao.deleteEmployee(6);
System.out.println(isDelete);
}
@Test
public void insertEmployee() {
Employee employee = new Employee();
employee.setEmpName("peter");
employee.setGender(0);
employee.setEmail("peter@gmail.com");
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
employeeDao.insertEmployee(employee);
System.out.println(employeeDao.getEmpById(2));
}
@After
public void tearDown() throws Exception {
openSession.close();
}
}
执行测试方法,验证项目是否可以成功运行
properties属性-引入外部文件
在resource目录下新建db.properties,配置数据库连接信息
代码语言:javascript复制jdbc_driver=com.mysql.cj.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
jdbc_username=root
jdbc_password=root
修改mybatis全局配置文件,引入properties,并修改数据库连接配置
在configuration标签下增加properties标签
代码语言:javascript复制<properties resource="db.properties" />
properties标签有两个属性,都可以标识引入文件的位置
- resource:从类路径下开始引用
- url:引用磁盘或者网络路径下的资源
修改datasource标签下的数据库连接配置,使用${}引用数据库配置文件的配置信息
代码语言:javascript复制<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}"/>
</dataSource>
执行getEmpById测试方法
一定要将properties放在第一个,否则会报错
settings属性-改变MyBatis运行时行为
settings是MyBatis中极为重要的配置,它会改变MyBatis的运行时行为。 mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即将数据库字段名 A_COLUMN 映射到实体类属性名 aColumn(数据库字段不区分大小写,但是区分是否有下划线“_”);默认是false即不开启
t_employee表增加一个字段create_time,并给字段赋值为当前时间,同时Employee实体类也需要增加一个属性createTime
代码语言:javascript复制@Data
public class Employee {
private Integer id;
private String empName;
private String email;
private Integer gender;
private Date createTime;
}
执行测试getEmpById()测试方法
createTime为空说明在数据库字段中没有找到createTime字段,而我们命名的字段为create_time,解决这个问题可以的办法是可以在修改SQL给查询字段增加别名使其与数据库字段一致害可以在mybatis全局配置中增加settings属性,开启自动驼峰命名转换,注意settings配置一定要在properties配置的下面
代码语言:javascript复制<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
- name:配置项的Key
- value:配置项的值 可以配置的Key有很多,具体可以点击此处查看
再次执行测试
成功获取到了createTime的值
typeAliases属性-为类型起别名
类型别名可为 Java 类型设置一个缩写名字。 它仅用于MyBatis全局 XML 配置,意在降低冗余的全限定类名书写
代码语言:javascript复制<typeAliases>
<typeAlias alias="Employee" type="com.citi.entity.Employee"/>
</typeAliases>
alias指定一个别名,如果不指定,默认就是类名
在需要起别名的类非常多的时候,可以通过package属性批量起别名
代码语言:javascript复制<typeAliases>
<package name="com.citi.entity"/>
</typeAliases>
批量的时候如果需要对某个类起一个非默认的别名,可以在实体类上增加注解@Alias增加别名 修改映射文件employee.xml中select标签,将返回内容resultType从com.citi.entity.Employee改为Employee,定义类别名之后就可以识别到
代码语言:javascript复制<select id="getEmpById" resultType="Employee">
select * from t_employee where id = #{id}
</select>
再次执行测试
推荐使用全类名,可以快速定位
typeHandlers属性-类型处理器
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。
代码语言:javascript复制<typeHandlers>
<!--配置自定义的类型处理器-->
<typeHandler handler="自定义类型处理器" />
</typeHandlers>
MyBatis已经定义好了大部分的类型处理器,遇到枚举类型可能需要进行自定义类型处理器。该配置使用频次较低
objectFactory(对象工厂)
MyBatis将查询到的数据使用objectFactory利用反射封装成对象,使用频次较低
plugins属性
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
插件通过动态代理机制,可以介入上面四大对象的任何一个方法的执行
environment属性-支持多环境切换
MyBatis通过environments标签配置多个环境,如开发、测试、生产环境等,可以通过default属性是指默认的环境或者切换环境
每一个environment指一个环境,id属性是这个环境的唯一标识
事务控制会使用Spring的事务控制,数据元配置会使用如druid、c3p0等数据库连接工具,不会使用原生的数据库驱动
databaseProvider-数据库移植
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId
属性。 MyBatis 会加载带有匹配当前数据库 databaseId
属性和所有不带 databaseId
属性的语句
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"></property>
<property name="Oracle" value="orcl"></property>
</databaseIdProvider>
SQL映射文件中可以根据不同的数据库增加不同的SQL语句
代码语言:javascript复制<select id="getEmpById" resultType="Employee" databaseId="orcl">
select * from t_employee where id = #{id}
</select>
使用频次较低
mappers-批量注册
我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="mappers/employee.xml"/>
</mappers>
代码语言:javascript复制<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/employee.xml"/>
</mappers>
代码语言:javascript复制<!-- 使用映射器接口实现类的完全限定类名,要保证xml文件和接口名相同并在同一目录下-->
<mappers>
<mapper class="com.citi.dao.EmployeeDao"/>
</mappers>
代码语言:javascript复制<!-- 将包内的映射器接口实现全部注册为映射器,要保证xml文件和接口名相同并在同一目录下 -->
<mappers>
<package name="com.citi.dao"/>
</mappers>