mybatis 3.x 的三种使用方式及全局配置文件

mybatis的设计理念:把SQL交给开发人员,把预编译、参数设置、sql执行、封装结果等步骤交给框架。

mybatis三种使用方式

传统使用方式示例

1) 必要的依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- logs 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

2) 代码结构 和 库表准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*代码结构*/
test01.sql_session_factory
|--Emp.java
|--Test01.java
|--mybatis-test01-config.xml
|--mybatis-test01-mapper.xml


/*创建数据库*/
create database if not exists test;
/*创建员工表*/
create table if not exists test.t_emp(
id int not null primary key auto_increment,
last_name varchar(50),
email varchar(50),
gender varchar(10)
);

3) mybatis-test01-config.xml(全局配置文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.1.96:3306/test" />
<property name="username" value="xxx" />
<property name="password" value="xxx" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="test01/sql_session_factory/mybatis-test01-mapper.xml" />
</mappers>
</configuration>

4) mybatis-test01-mapper.xml(SQL映射文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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">
<!--
namespace: 名称空间(此处暂时名字任意)
resultType: 返回数据的类型
#{xxx}: 传递过来的参数值
-->
<mapper namespace="test01.sql_session_factory">
<select id="selectEmp" resultType="test01.sql_session_factory.Emp">
select id, last_name as lastName, email, gender from t_emp where id = #{id}
</select>
</mapper>

5) Emp.java

1
2
3
4
5
6
7
public class Emp {
private Integer id;
private String lastName;
private String email;
private String gender;
// geter/setter ...
}

6) Test01.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
SqlSession对象代表和数据库的一次会话,用完之后必须关闭。
SqlSession和connection一样都是非线程安全的,每次使用都应该获取新的sqlsession对象。
*/
@Test
public void createSqlSessionFactoryWithXML() throws IOException {
// 创建 SqlSessionFactory
String resource = "test01/sql_session_factory/mybatis-test01-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
System.err.println(sqlSessionFactory);

SqlSession session = null;
try {
// 获取 SqlSession
session = sqlSessionFactory.openSession();
Emp emp = session.selectOne("selectEmp", 1);
System.err.println(emp);
} finally {
session.close();
}
}

@Test
public void createSqlSessionFactoryWithoutXML() {
// 数据源
Properties properties = new Properties();
properties.setProperty("driver", "com.mysql.jdbc.Driver");
properties.setProperty("url", "jdbc:mysql://192.168.1.96:3306/test");
properties.setProperty("username", "xxx");
properties.setProperty("password", "xxx");
PooledDataSourceFactory pooledDataSourceFactory = new PooledDataSourceFactory();
pooledDataSourceFactory.setProperties(properties);
DataSource dataSource = pooledDataSourceFactory.getDataSource();
// 事务
TransactionFactory transactionFactory = new JdbcTransactionFactory();
//
Environment environment = new Environment("development",
transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(Mapper.class);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(configuration);
System.err.println(sqlSessionFactory);
}

使用接口方式示例(推荐)

1) 在方式一的基础上增加 EmpMapper 接口

1
2
3
4
// 接口式编程,将DAO层的定义和实现解耦
public interface EmpMapper {
Emp getEmpById(Integer id);
}

2) mapper映射文件绑定 Mapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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">
<!--
1、命名空间namespace必须与Mapper接口全类名相同
2、sql语句id必须与Mapper接口的方法名相同
说明:当使用package批量注册SQL映射文件时,则要求mapper映射
文件(如果有)和mapper接口必须在同一个包下,并且名称相同
-->
<mapper namespace="test02.sql_session_factory.EmpMapper">
<select id="getEmpById" resultType="test02.sql_session_factory.Emp">
select id, last_name as lastName, email, gender from t_emp where id = #{id}
</select>
</mapper>

3) 测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void createSqlSessionFactoryWithXML() throws IOException {
// 创建 SqlSessionFactory
String resource = "test02/sql_session_factory/mybatis-test02-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
System.err.println(sqlSessionFactory);

// 通过 session 获取 mapper
SqlSession session = null;
try {
session = sqlSessionFactory.openSession();
EmpMapper empMapper = session.getMapper(EmpMapper.class);
Emp emp = empMapper.getEmpById(1);
System.err.println(empMapper); // xxx.MapperProxy@87f383f
System.err.println(emp);
} finally {
session.close();
}
}

使用注解映射SQL示例(应用和SQL耦合,不推荐)

1) 编写mapper接口

1
2
3
4
public interface EmpAnnotationMapper {
@Select("select * from t_emp where id=#{id}")
Emp getEmpById(Integer id);
}

2) 引入SQL映射接口

1
2
3
<mappers>
<mapper class="test03.configuration.EmpAnnotationMapper"/>
</mappers>

3) 测试(略)

全局配置文件简介

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?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标签引入外部properties配置文件中的内容(一般的spring项目会把配置工作交给spring来做)
resource: 引入外部properties配置文件
url: 引入网络或磁盘路径下的properties配置文件

注意mybatis将会按照以下顺序来加载运行时属性:
1. 在properties元素体内定义的属性首先被加载;
2. 然后读取properties元素中resource和url加载的属性,他会覆盖已读取的同名属性;
3. 最后读取parameterType传递的属性,它会覆盖已读取的同名属性;

因此,通过parameterType传递的属性具有最高的优先级,resource或url加载的属性次之,
properties元素体内定义的属性优先级最低。建议不要在properties元素体内添加任何属性,
并且在properties配置文件中定义的属性要有一定的特殊性。
-->
<properties resource="test03/configuration/jdbc.properties">
<!-- peoperty ... -->
</properties>


<!--
配置管理:
mybatis默认预定义的setting参见:org.apache.ibatis.builder.xml.XMLConfigBuilder#settingsElement
-->
<settings>
<!-- 文档参照: http://www.mybatis.org/mybatis-3/zh/configuration.html#settings -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>


<!--
别名管理:
针对parameterType或resultType所指定的类型定义一些别名,在mapper.xml中通过别名定义parameterType或resultType所指定的类型,方便开发。
注意:如果一个包下的子包中也有相同别名的类,可以使用 @Alias 注解为类指定新的别名以避免冲突
建议:写全类名以方便开发
参考:常见的Java类型内建的相应的类型别名参照
org.apache.ibatis.type.TypeAliasRegistry
http://www.mybatis.org/mybatis-3/zh/configuration.html
-->
<typeAliases>
<!-- 为java类型起别名,type指定全类型,alias指定别名(如果不指定则默认为类名首字母小写) -->
<!-- <typeAlias type="test03.configuration.Emp"/> -->
<!-- 为某个包及其下的子包的所有类批量起别名(默认别名为类名首字母小写,实际上别名不区分大小写) -->
<package name="test03.configuration"/>
</typeAliases>


<!--
typeHandlers:
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,
都会用类型处理器将获取的值以合适的方式转换成 Java 类型。mybatis定义了一些默认的类型处理器。
mybatis预定义的typeHandlers参见:org.apache.ibatis.type.TypeHandlerRegistry

另外你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。
具体做法为: 实现 org.apache.ibatis.type.TypeHandler 接口,或继承一个很便利的类
org.apache.ibatis.type.BaseTypeHandler,然后可以选择性地将它映射到一个 JDBC 类型。
-->
<typeHandlers>
<!-- <typeHandler handler="" javaType="" jdbcType=""/> -->
</typeHandlers>


<!--
插件管理:
MyBatis允许你在已映射语句执行过程中的某一点进行拦截调用(实际还是代理)。
默认情况下,MyBatis允许使用插件来拦截的方法调用包括:
Executor (update, query, flushStatements, commit, rollback,
getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
使用插件需要很小心,因为如果在试图修改或重写已有方法的行为的时候,你很可能会修改MyBatis的核心模块。
-->
<!--
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
-->


<!--
environments:
1、可以配置多个environment,但创建SessionFactory的时候只能选择其一。
2、每个environment标签下必须包含 transactionManager 和 dataSource 两个子标签。
3、事务管理器transactionManager的可选值有 JDBC|MANAGED。
JDBC: 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED: 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(
比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要使用其下
property子标签将closeConnection 属性设置为false来阻止它默认的关闭行为。
其实这两个可选值它们是类型别名(参照 org.apache.ibatis.session.Configuration),换句话说,
通过实现 TransactionFactory接口 可以自定义事务,并使用实现类的完全限定名或类型别名代替 JDBC|MANAGED。
注意:如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为Spring模块会使用自带的管理器来覆盖前面的配置。
4、数据源dataSource的可选值有 UNPOOLED|POOLED|JNDI。
通过实现 DataSourceFactory接口 可以设置自定义的数据源(eg. c3p0、druid等)
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<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>
</environment>
</environments>


<!--
databaseIdProvider:
Mybatis对多数据库厂商的支持,方法如下:
1、定义数据库厂商标识的别名:多数据库厂商支持,作用就是根据数据库厂商的标识。驱动包实现方法
DatabaseMetaData#getDatabaseProductName可以获取厂商标识。由于通常情况下这个字符串
都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短。
2、设置具体sql语句相关标签的databaseId属性为当前数据库厂商标识别名,如:
<select id="getEmpById" resultType="emp" databaseId="mysql">xxx<select>
3、配置相应数据库的 environment,并设置为默认环境。
-->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle" />
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
</databaseIdProvider>


<!--
mappers:
1、使用映射文件映射SQL(推荐)
将SQL映射注册到全局配置中。
resource:引用类路径下的sql映射文件
url:引用网络路径下的sql映射文件
package:用于批量注册,要求mapper映射文件(如果有)和mapper接口必须在同一个包下,并且名称相同。
class:a、引用mapper接口,如果使用class注册mapper接口,那么mapper
映射文件必须和mapper接口在同一个目录下,并且具有相同的名称。
b、class标签也可以直接注册使用注解映射SQL的mapper接口。

2、使用注解映射SQL
在这种情况下,所有的SQL都是使用注解写在接口上,并且使用class标签将接口注册进来。
-->
<mappers>
<package name="test03.configuration"/>
<!--
<mapper resource="test03/configuration/EmpMapper.xml" />
<mapper class="test03.configuration.EmpAnnotationMapper"/>
-->
</mappers>
</configuration>