1、介绍
1.1、MyBatis是什么
- MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- MyBatis 可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO( Plain Old Java Objects,普通的Java对象)映射成数据库中的记录
1.2、MyBatis历史
- 原是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis ,代码于2013年11月迁移到Github(下载地址见后)。
- iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
1.3、MyBatis优势
- SQL夹在Java代码块里,耦合度高导致硬编码内伤
- 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见
- – 长难复杂SQL,对于Hibernate而言处理也不容易,
- – 内部自动生产的SQL,不容易做特殊优化,Hibernate中要优化,自己编写HQL,还得学习
- – 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难,导致数据库性能下降
- 对开发人员而言,核心sql还是需要自己优化
- sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据
2、编程方式
2.1、配置文件方式
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
}
<?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">
<!--
namespace:名称空间;通常指定为接口的全类名
id:唯一标识
resultType:返回值类型
#{id}:从传递过来的参数中取出id值
public Employee getEmpById(Integer id);
-->
<select id="getEmpById" resultType="com.qdc.test.Employee">
select id,last_name lastName,email,gender from employee where id = #{id}
</select>
</mapper>
<?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?useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT" />
<property name="username" value="root" />
<property name="password" value="" />
</dataSource>
</environment>
</environments>
<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
<mappers>
<mapper resource="EmployeeMapper.xml" />
</mappers>
</configuration>
package com.qdc.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;
import java.io.InputStream;
public class MyTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* 1、根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象 有数据源一些运行环境信息
* 2、sql映射文件;配置了每一个sql,以及sql的封装规则等。
* 3、将sql映射文件注册在全局配置文件中
* 4、写代码:
* 1)、根据全局配置文件得到SqlSessionFactory;
* 2)、使用sqlSession工厂,获取到sqlSession对象使用他来执行增删改查
* 一个sqlSession就是代表和数据库的一次会话,用完关闭
* 3)、使用sql的唯一标志来告诉MyBatis执行哪个sql。sql都是保存在sql映射文件中的。
*
* @throws IOException
*/
@Test
public void test() throws IOException {
// 2、获取sqlSession实例,能直接执行已经映射的sql语句
// sql的唯一标识:statement Unique identifier matching the statement to use.
// 执行sql要用的参数:parameter A parameter object to pass to the statement.
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
Employee employee = openSession.selectOne(
"abc.getEmpById", 1);
System.out.println(employee);
} finally {
openSession.close();
}
}
}
2.2、接口方式
public interface EmployeeMapper {
public Employee getEmpById(Integer id);
}
<?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.qdc.test.EmployeeMapper">
<!--
namespace:名称空间;通常指定为接口的全类名
id:唯一标识
resultType:返回值类型
#{id}:从传递过来的参数中取出id值
public Employee getEmpById(Integer id);
-->
<select id="getEmpById" resultType="com.qdc.test.Employee">
select id,last_name lastName,email,gender from employee where id = #{id}
</select>
</mapper>
<mappers>
<mapper resource="EmployeeMapper.xml" />
<mapper resource="EmployeeMapper2.xml" />
</mappers>
@Test
public void test02() throws IOException {
// 1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// 2、获取sqlSession对象
SqlSession openSession = sqlSessionFactory.openSession();
try {
// 3、获取接口的实现类对象
//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = mapper.getEmpById(1);
System.out.println(mapper.getClass());
System.out.println(employee);
} finally {
openSession.close();
}
}
3.3、小结
- SqlSession代表和数据库的一次会话,用完就必须关闭
- SqlSession和Connection都是非线程安全的,每次使用都应该去获取新的对象
- 接口方式中,mapper接口中没有实现类,但是MyBatis会为这个接口生成一个代理对象
4、全局配置文件
4.1、dtd约束
4.2、引入外部配置文件
- 配置文件<configuration>标签中加入<properties>
4.3、settings配置
设置参数 | 描述 | 有效值 | 默认值 |
---|
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true/false | TRUE |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时。所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 | true/false | FALSE |
useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true/false | TRUE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则( camel case )映射即从经典数据库列名A_ COLUMN到经典Java属性名aColumn的类似映射 | true/false | FALSE |
- mapUnderscoreToCamelCase举例,<settings>标签不能放在第一个和最后一个(在environments之前)
4.4、typeAliases别名配置
别名 | 映射的类型 | 别名 | 映射的类型 | 别名 | 映射的类型 |
---|
_byte | byte | string | String | date | Date |
_long | long | byte | Byte | decimal | BigDecimal |
_short | short | long | Long | bigdecimal | BigDecimal |
_int | int | short | Short | object | Object |
_integer | int | int | Integer | map | Map |
_double | double | integer | Integer | hashmap | HashMap |
_float | float | double | Double | list | List |
_boolean | boolean | float | Float | arraylist | ArrayList |
- | - | boolean | Boolean | collection | Collection |
- | - | - | - | iterator | Iterator |
4.5、typeHandlers类型处理器简介
类型处理器 | Java 类型 | JDBC 类型 |
---|
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short, short | 数据库兼容的 NUMERIC 或 SHORT INTEGER |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long, long | 数据库兼容的 NUMERIC 或 LONG INTEGER |
FloatTypeHandler | java.lang.Float, float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double, double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
4.6、plugins-插件简介
- 通过插件来修改MyBatis的一些核心行为。 插件通过动态代理机制,可以介入四大对象的任何一个方法的执行。
4.7、enviroments运行环境
- 可以在<enviroments>标签中配置多个环境(数据库实例),比如生产、测试使用不同的环境,配置多个相同环境也可
- 在<enviroments>标签中的default属性中设置使用哪个环境(切换数据库)
- id:指定当前环境的唯一标识
- transactionManager、dataSource都必须有
4.7.1、transactionManager
- 负责事务管理(目前一般使用Spring实现事务管理)
- 类型: JDBC | MANAGED | 自定义
- JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围
- MANAGED:不提交或回滚一个连接、让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)
- 自定义:实现TransactionFactory接口
4.7.2、dataSource
- 配置数据源,就是数据库配置
- 类型: UNPOOLED | POOLED | JNDI | 自定义
- UNPOOLED:不使用连接池, UnpooledDataSourceFactory
- POOLED:使用连接池, PooledDataSourceFactory
- NDI: 在EJB 或应用服务器这类容器中查找指定的数据源
- 自定义:实现DataSourceFactory接口,定义数据源的获取方式
4.8、databaseIdProvider多数据库支持
- MyBatis 可以根据不同的数据库厂商执行不同的语句,就是一句sql语句可以在不同数据库中执行
- type: DB_VENDOR 使用MyBatis提供的VendorDatabaseIdProvider解析数据库厂商标识。也可以实现DatabaseIdProvider接口来自定义。
- property-name:数据库厂商标识
- property-value:为标识起一个别名,方便SQL语句使用databaseId属性引用
- 在mapper文件中的select标签属性中设定所使用的的数据库(别名)
- Mybatis匹配规则:
- 如果没有配置<databaseIdProvider>标签,那么databaseId属性的值为null(即使用默认的数据库,<enviroments>标签中的default属性中设置使用哪个环境)
- 如果配置了<databaseIdProvider>标签,那么使用配置的name去匹配数据库,如果匹配上了就使用,如果匹配不上databaseId依旧为空(即使用默认的数据库)
- 如果databaseId匹配成功,那么只会在匹配到的数据库中进行操作,不会在其他数据库上操作了
- MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时找到两个id相同的sql语句(select标签),一个带有databaseId,一个不带,那么不带的会被抛弃
4.9、mappers,sql映射注册
- 其实就是告诉MyBatis去哪里寻找sql映射文件
- 在<mappers>标签中可以添加多个<mapper>标签
- 利用resource参数:使用相对于类路径的资源引用
- 有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下
- 没有sql映射文件,所有的sql都是利用注解写在接口上
- 一般来说,复杂的Dao接口会写成sql映射文件,简单的直接使用注解
4.10、小结-标签顺序