1.1 什么是mybatis
Mybatis: Object relation mapping 对象关系映射
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
2013年11月迁移到Github。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
1.2 .mybatis 优缺点
- 优点
- 易于上手和掌握。
- sql写在xml里,便于统一管理和优化。
- 解除sql与程序代码的耦合。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
- 缺点
- sql工作量很大,尤其是字段多、关联表多时,更是如此。
- sql依赖于数据库,导致数据库移植性差。
- 由于xml里标签id必须唯一,导致DAO中方法不支持方法重载。
- 字段映射标签和对象关系映射标签仅仅是对映射关系的描述,具体实现仍然依赖于sql。(比如配置了一对多Collection标签,如果sql里没有join子表或查询子表的话,查询后返回的对象是不具备对象关系的,即Collection的对象为null)
- DAO层过于简单,对象组装的工作量较大。
- 不支持级联更新、级联删除。
- 编写动态sql时,不方便调试,尤其逻辑复杂时。
- 缓存使用不当,容易产生脏数据。
1.3.mybatis 入门
- 创建普通的 maven 项目
- 导入相关的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wy</groupId>
<artifactId>mybatis</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>mybatis-01</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
mysql 驱动和数据库的版本要求如下:
1.3.1 新建数据库和表
首先创建一个数据库,编码方式为 UTF-8
create database demo default character set utf8 collate utf8_general_ci;
然后再创建一个名为t_user的表并插入一些数据
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(100) NOT NULL,
`age` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
1.3.2 添加mybatis全局配置文件
使用XML形式进行配置,首先在src/main/resources mybatis 目录下 创建 mybatis-config.xml 配置文件
db.properties
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://192.168.0.22:3306/demo?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=root
<?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>
<properties resource="db.properties"></properties>
<settings>
<!-- logImpl 属性配置 指定使用 LOG4J 输出日志 -->
<setting name="logImpl" value="LOG4J"/>
<!-- 启动驼峰规则,这样在map文件中带下划线的column会自动按照驼峰命名规则映射到实体属性变量中。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.xa.domain"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<!-- <mapper class="com.xa.mapper.UserMapper"></mapper>-->
</mappers>
</configuration>
上面的配置详情如下:
-
中的logImpl 属性配置指定使用LOG4J输出日志
-
元素下面配置了一个包的别名,通常确定一个类的时候需要确定需要使用类用到的类的全限定名称,在Mybatis 中需要频繁用到类的
全限定名称,为了方便使用,我们配置了 com.xa.domain 包,这样配置后,在使用类的时候不需要写包名的部分。只使用User即可。
-
中配置了数据库连接信息
-
中配置了一个完整类路径的UserMapper
1.3.3 创建实体类和Mapper.xml文件
关于Mapper的命名方式:在MyBatis 中,根据Mybatis 官方的习惯,一般用Mapper作为XML和接口类名的后缀,这里的Mapper通常和常用的DAO后缀类似。
1.创建实体类 User
在src/main/java 下创建一个包 com.xa.domain 在这个包创建一个User对象
public class User {
private Long id;
private String username;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.创建接口类UserMapper
public interface UserMapper {
User selectUserById(Integer id);
Integer insertUser(User user);
Integer updateUser(User user);
Integer deleteUser(Integer id);
}
由于每次调用的时候都要去找statement 以及拼接参数,使用上特别不友好,所以 mybatis 引入了接口的机制,将接口mapper.xml 的namespace 名称绑定,mybatis 就可以根据ASM工具动态构建该接口的实例。
mapper 映射器接口的实例,通过sqlSession.getMapper(Class type ) 就可以获取mapper实例,该实例的作用域在方法内。
3.在src/main/resources 下面创建 mapper文件夹,在该文件夹下创建 UserMapper.xml
<?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="cn.xa.mapper.UserMapper">
<!--根据id查询Emp实体-->
<select id="selectUserById" resultType="com.xa.domain.User">
select * from t_user where id = #{id}
</select>
<insert id="insertUser">
INSERT INTO t_user(user_name,age ) VALUES (#{userName},#{age});
</insert>
<update id="updateUser">
UPDATE t_user
SET user_name=#{userName},age = #{age}
WHERE id=#{id}
</update>
<delete id="deleteUser">
DELETE FROM t_user WHERE id=#{id}
</delete>
</mapper>
-
xml 的根元素,属性 namespace 定义了当前XML 的命名空间。mybatis就是通过这个值讲接口和XML关联起来。
-
·
定义了一个select 查询,id表示要匹配的方法的名称,和 namespace对应的接口中的方法匹配,resultType 表示返回值的类型,查询操作必须要包含返回值的类型。#{属性名} 表示要传入的参数的名称。
1.3.4 配置Log4j
在src/main/resources 中添加 log4j,proerties 配置文件,输入以下内容。
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面代码
log4j.rootLogger=DEBUG,CONSOLE,file
# 输出控制台的相关设置
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Threshold=DEBUG
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%c]-%m%n
###日志输出级别
log4j.logger.org.mybatis = DEBUG
log4j.logger.java.sql= DEBUG
log4j.logger.java.sql.Statement= DEBUG
log4j.logger.java.sql.ResultSet= DEBUG
log4j.logger.java.sql.PreparedStatement = DEBUG
1.3.5 编写测试类
package com.xa.test;
/**
* @author admin
* @description: TODO
* @date 2022/9/5 22:27
*/
public class UserTest {
SqlSessionFactory sqlSessionFactory;
@Before
public void init(){
// 从 XML 中构建 SqlSessionFactory
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* 基于StatementId的方式去执行SQL
* <mapper resource="mapper/UserMapper.xml"/>
* @throws IOException
*/
@Test
public void test01() {
// 表示跟数据库的一次会话
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
User user = (User) sqlSession.selectOne(
"com.xa.mapper.UserMapper.selectUserById", 2);
System.out.println(user);
}finally{
sqlSession.close();
}
}
/**
* 基于接口绑定的方式
*/
@Test
public void test02(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUserById(2);
System.out.println(user);
}finally{
sqlSession.close();
}
}
@Test
public void testInsert(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Integer count = mapper.insertUser(new User("jack",33));
System.out.println(count);
sqlSession.commit();
}finally{
sqlSession.close();
}
}
@Test
public void testUpdate(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Integer count = mapper.updateUser(new User(2l,"tom",20));
System.out.println(count);
sqlSession.commit();
}finally{
sqlSession.close();
}
}
@Test
public void testDelete(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Integer count = mapper.deleteUser(2);
System.out.println(count);
}finally{
sqlSession.close();
}
}
}
在测试之前,需要通过 mybatis-config.xml 文件来初始化SqlSessionFactory 类
@Before
public void init(){
// 从 XML 中构建 SqlSessionFactory
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
首先通过Resources工具类加载mybatis-config.xml 配置文件。
再通过 SqlSessionFactoryBuilder 建造类来创建SqlSessionFactory, 首先解析mybatis-config.xml 配置文件,读取配置文件中的mappers 配置后会读取全部的Mapper.xml 进行具体方法的解析,在这些解析完成后,SqlSessionFactory 就包含了所有的属性配置和执行SQL的信息。
测试案例一
基于StatementId 的方式去执行SQL
/**
* 基于StatementId的方式去执行SQL
* <mapper resource="mapper/UserMapper.xml"/>
* @throws IOException
*/
@Test
public void test01() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
User user = (User) sqlSession.selectOne(
"com.xa.mapper.UserMapper.selectUserById", 2);
System.out.println(user);
}finally{
sqlSession.close();
}
}
上面代码首先通过SqlSessionFactory 工厂对象创建一个SqlSession .
通过SqlSession 的selectUserById 方法查询 UserMapper 中id = "selectUserById"的方法,执行SQL查询,mybatis底层使用JDBC执行SQL,获得查询结果集ResultSet后,根据resultType 的配置将结果映射为 user 类型的对象,返回查询结果。
测试结果如下:
[com.xa.mapper.UserMapper.selectUserById]-==> Preparing: select * from t_user where id = ?
[com.xa.mapper.UserMapper.selectUserById]-==> Parameters: 2(Integer)
[com.xa.mapper.UserMapper.selectUserById]-<== Total: 1
User{id=2, username='null', age=20}
测试案例二
基于接口的绑定:
/**
* 基于接口绑定的方式
* @throws IOException
*/
@Test
public void test02(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
}finally{
sqlSession.close();
}
}
测试案例二是直接获取UserMapper接口,直接执行
测试结果为:
[com.xa.mapper.UserMapper.selectUserById]-==> Preparing: select * from t_user where id = ?
[com.xa.mapper.UserMapper.selectUserById]-==> Parameters: 2(Integer)
[com.xa.mapper.UserMapper.selectUserById]-<== Total: 1
User{id=2, username='张三', age=20}
1.4. 全局文件配置
mybatis 中配置文件的结构如下:
<configuration>
<properties/><!--属性 -->
<settting/> <!-- 全局配置参数 -->
<typeHandlers/> <!-- 类型处理器 -->
<..../>
<plugins> <!-- 插件 -->
<mappers/><!-- 映射器 -->
</configuration>
1.4.1 配置环境(environments)
mybatis允许配置多个环境。比如 我们的项目一般会在多个环境使用,比如开发环境、测试环境、生产环境等进行部署,每个环境的数据库参数都是不同的。
在mybatis 中可以通过 environment 来设置不同环境的属性。
使用场景:
- 为了设置不同的数据库配置
- 测试和生产使用不同的数据库
- 有多个数据库却共享相同的模式,即对不同的数据库使用相同的SQL映射
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
代码如下:
<!-- 对事务的管理和连接池的配置 -->
<environments default="oracle_jdbc">
<environment id="oracle_jdbc">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.oracle.driverClassName}" />
<property name="url" value="${jdbc.oracle.url}" />
<property name="username" value="${jdbc.oracle.username}" />
<property name="password" value="${jdbc.oracle.password}" />
</dataSource>
</environment>
<environment id="mysql_jdbc">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.mysql.driverClassName}" />
<property name="url" value="${jdbc.mysql.url}" />
<property name="username" value="${jdbc.mysql.username}" />
<property name="password" value="${jdbc.mysql.password}" />
</dataSource>
</environment>
</environments>
用default指定默认的数据库链接::
- 默认使用的环境 ID(比如:default=“oracle_jdbc”)。
- 每个 environment 元素定义的环境 ID(比如:id=“mysql_jdbc”)。
- 事务管理器的配置(比如:type=“JDBC”)。
- 数据源的配置(比如:type=“POOLED”)。
一个数据库对应一个SqlSessionFactory,为了明确使用哪种环境,需要在SqlSessionFactory 中指定environnment.
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);
如果不传环境参数,那么默认环境将会被加载。
在开发的时候,如若向使用mysql jdbc,则可以通过
// 从 XML 中构建 SqlSessionFactory
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"mysql_jdbc");
1.4.2 属性 Properties
properties 元素可以通过 resource 或 url 加载外部的 properties文件中的属性,也可以直接设置 property 属性。然后在xml中可以
通过${属性名} 进行替换。
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
从 MyBatis 3.4.2 开始,你可以为占位符指定一个默认值。例如:
<dataSource type="POOLED">
<property name="username" value="${username:xxxx}"/>
</dataSource>
如果属性 username 没有被设置,则默认为xxx。
这个特性默认是关闭的。如果你想为占位符指定一个默认值,你应该添加一个指定的属性来开启这个特性。例如:
<properties>
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
</properties>
注意: mybatis 会按照下面的顺序来加载属性
- 在properties 元素体内定义的属性首先被读取。
- 然后会读取properties 元素中的resource 或 url 加载的属性,它会覆盖已经读取同名的属性。
1.4.3 设置 settings
用来设置Mybatis全局参数,约定mybatis 的全局行为。比如: 开启二级缓存、开启延迟加载。具体配置如下L:
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 | true|false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true|false | false |
aggressiveLazyLoading | 当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods )。 | true|false | false (在 3.4.1 及之前的版本默认值为 true) |
multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要驱动支持)。 | true|false | true |
useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true|false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动支持。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能支持但仍可正常工作(比如 Derby)。 | true|fasle | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或者未知属性类型)的行为。 | NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true|false | False |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true|false | false |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION|STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL, VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | 一个类型别名或完全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) | 一个类型别名或完全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J/LOG4J/LOG4J2/JDK_LOGGING/COMMONS_LOGGING/STDOUT_LOGGING/NO_LOGGING | 未设置 |
proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB|JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) | true|false | true |
configurationFactory | 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) | 类型别名或者全类名. | 未设置 |
<settings>
<setting name="cacheEnabled" value="true"/>
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--<setting name="multipleResultSetsEnabled" value="true"/>-->
<!--<setting name="useColumnLabel" value="true"/>-->
<!--<setting name="useGeneratedKeys" value="false"/>-->
<!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
<!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
<!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
<!--<setting name="defaultStatementTimeout" value="25"/>-->
<!--<setting name="defaultFetchSize" value="100"/>-->
<!--<setting name="safeRowBoundsEnabled" value="false"/>-->
<!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
<!--<setting name="localCacheScope" value="STATEMENT"/>-->
<!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
<!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
<!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
</settings>
1.4.4 类型别名 (typeAliases)
我们在mapper.xml 中会定义很多的statement,而statement使用parameterType 来指定输入的参数,使用resultType来指定输出结果的映射类型。如果都指定全路径的话,不方便进行开发,所以可以使用对 parameterType 或 resultType 指定的类型定义一些别名,在mapper.xml 中可以通过设置别名,方便开发。
typeAliases 是mybatis 提供的别名转换器,配置如下:
<typeAliases>
<package name="com.xa.domain"/>
</typeAliases>
上面配置的是 批量的别名定义,扫描整个包下的类,别名为类名(首字母大写或者小写都可以),也可以为每个实体类设置一个别名。
<!--根据id查询Emp实体-->
<select id="selectUserById" resultType="User">
select * from t_user where id = #{id}
</select>
配置好后,在resultType 中可以直接使用类名来代表全路径。
1.4.5 类型处理器(typeHanders)
用于将预编译语句(PreparedStatement) 或结果集 (ResultSet)中的JDBC类型转换成Java类型。
*
TypeHandler 的两个作用是 设置参数 与 获取结果。
<typeHandlers>
<typeHandler handler="com.xa.typehandler.ExampleTypeHandler" />
</typeHandlers>
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean , boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte , byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short , short | 数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer , int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long , long | 数据库兼容的 NUMERIC 或 BIGINT |
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 |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB , LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR , NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB , LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
1.4.6 对象工厂 objectFactory
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。比如:
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
public Object create(Class type) {
return super.create(type);
}
public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) {
return super.create(type, constructorArgTypes, constructorArgs);
}
public void setProperties(Properties properties) {
super.setProperties(properties);
}
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}}
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 最后,setProperties 方法可以被用
来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, objectFactory 元素体中定义的属性会被传递给 setProperties 方法。
1.4.7 插件 (plugins)
mybatis 提供插件的方式来拦截映射
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--默认值为 false,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果-->
<!--如果某些查询数据量非常大,不应该允许查出所有数据-->
<property name="pageSizeZero" value="true"/>
</plugin>
</plugins>
后面有章节详细介绍 插件。
1.4.8 SQL 映射文件(mappers)
SQL 映射文件,mapper配置有以下几种方法
1.<mapper resource = ""/>
使用相对类路径的资源。
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
<mapper class =""/>
使用mapper 接口类路径
<mappers>
<mapper class="com.xa.mapper.UserMapper"></mapper>
</mappers>
注意: 此种方法要求mapper接口和mapper映射xml文件名称相同,且放在同一个目录中
3.<package name=""/>
如果项目中的Mapper接口和Mapper.xml 越来越多,如果用下面的形式下载,则会加载很多行。
<mapper resource="mapper/UserMapper.xml"/>
那么有没有更方便的方法呢?
可以使用自动扫描包,具体做法如下,在 mybatis-config.xml中配置
<mappers>
<package name = "com.xa.mapper"/>
</mappers>
注册指定包下的Mapper皆苦
注意: 此种方法要求mapper接口和mapper映射文件名称相同,并且放在同一个目录中,