9.2 深入MyBatis的配置文件

MyBatis的持久化操作离不开SqlSessionFactory对象,这个对象是整个数据库映射关系经过编译后的内存镜像,该对象由SqlSessionFactoryBuilder加载MyBatis的配置文件产生。
SqlSessionFactory对象的openSession()方法可以打开Sqlsession对象。

代码回顾

1
2
3
4
5
// 读取mybatis-config.xml文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml"));
// 读取配置文件,初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession();

上述代码的功能是根据配置文件mybatis-config.xml,创建SqlSessionFactory对象,然后产生Sqlsession,执行SQL语句。

MyBatis的初始化

MyBatis的初始化就发生在第4句:

1
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

MyBatis初始化基本过程

SqlSessionFactoryBuilder根据传入的输入流生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例。

初始化的基本过程如下图所示:
这里有一张图片

MyBatis初始化要经过以下几步:

  1. 调用SqlSessionFactoryBuilder对象的build(inputstream)方法。
  2. SqlSessionFactoryBuilder会根据输入流inputstream等信息创建XMLConfigBuilder对象。
  3. SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法。
  4. XMLConfigBuilder对象解析XML配置文件返回Configuration对象。
  5. SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象。
  6. SqlSessionFactoryBuilder返回DefaultSessionFactory对象给客户端,供客户端使用。

由此可见,SqlsessionFactory是根据MyBatis的配置文件mybatis-config.xml创建的

9.2.1 MyBatis的配置文件结构

MyBatis的配置文件包含了影响MyBatis行为的信息。 文档的结构如下:

  • 顶层configuration配置
  • properties属性
  • settings设置
  • typeAliases类型命名
  • typeHandlers类型处理器
  • objectFactory对象工厂
  • plugins插件
  • environments环境
  • environment环境变量
  • transactionManager事务管理器
  • dataSource数据源
  • databaseIdProvider数据库厂商标识
  • mappers映射器

9.1.2 SqlSession

SqlSessionMyBatis的关键对象,它是执行持久化操作的对象,类似于JDBC中的Connection。它是应用程序与持久存储层之间执行交互操作的一个单线程对象,也是MyBatis执行持久化操作的关键对象。SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行已映射的SQL语句。

SqlSession要单独使用

每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的,绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中比如Serlvet当中的HttpSession对象中。

SqlSession用完要关闭

使用完SqlSession之后关闭Session很重要,应该确保使用finally块来关闭它.

SqlSession常用方法

SqlSession的常用方法如下:

insert

方法 描述
int insert(String statement)
  • 插入方法,
  • 参数statement是在配置文件(MyBatis XML Mapper)中定义的<insert>元素的id,
  • 返回执行SQL语句所影响的行数。
int insert(String statement,Object parameter)
  • 插入方法,
  • 参数statement是在配置文件中定义的<insert>元素的id,
  • parameter是插入所需的参数,通常是对象或者Map,
  • 返回执行SQL语句所影响的行数。

update

方法 描述
int update(String statement)
  • 更新方法,
  • 参数statement是在配置文件中定义的<update>元素的id,
  • 返回执行SQL语句所影响的行数。
int update(String statement,Object parameter)
  • 更新方法,
  • 参数statement是在配置文件中定义的<update>元素的id,
  • parameter是插入所需的参数,通常是对象或者Map,
  • 返回执行SQL语句所影响的行数。

delete

方法 描述
int delete(String statement)
  • 删除方法,
  • 参数statement是在配置文件中定义的<delete>元素的id。
  • 返回执行SQL语句所影响的行数。
int delete(String statement,Object parameter)
  • 删除方法,
  • 参数statement是在配置文件中定义的<delete>元素的id,
  • parameter是插入所需的参数,
  • 通常是对象或者Map,返回执行SQL语句所影响的行数。

select

selectOne

方法 描述
<T> T selectOne(String statement)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id。
  • 返回执行SQL语句查询结果的泛型对象,
  • 通常查询结果只有一条数据时才使用。
<T> T selectOne(String statement,Object parameter)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • parameter是查询所需的参数,通常是对象或者Map,
  • 返回执行SQL语句查询结果的泛型对象,
  • 通常查询结果只有一条数据时才使用。

selectList

方法 描述
<E> List<E> selectList(String statement)
  • 查询方法,
  • 参数是在配置文件中定义的<select>元素的id,
  • 返回执行SQL语句查询结果的泛型对象的集合。
<E> List<E> selectList(String statement,Object parameter)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • parameter是查询所需的参数,通常是对象或者Map,
  • 返回执行SQL语句查询结果的泛型对象的集合。
<E> List<E> selectList(String statement,Object parameter,RowBounds rowBounds)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • parameter是查询所需的参数,通常是对象或者Map。
  • RowBounds对象用于分页,它的两个属性:
    offset指查询的当前页数;
    limit指当前页显示多少条数据。
  • 返回执行SQL语句查询结果的泛型对象的集合。

selectMap 查询一列

方法 描述
<K,V> Map<K,V> selectMap(String statement,String mapKey)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • mapKey是返回数据的其中一个列名,
  • 执行SQL语句查询的结果将会被封装成一个Map集合返回,
    key就是参数mapKey传入的列名,
    value是封装的对象。
<K,V> Map<K,V> selectMap(String statement,Object parameter,String mapKey)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • parameter是查询所需的参数,通常是对象或者Map,
  • mapKey是返回数据的其中一个列名,
  • 执行SQL语句查询的结果将会被封装成一个Map集合返回,
    key就是参数mapKey传入的列名,
    value是封装的对象。

多表查询

方法 描述
void select(String statement,ResultHandle rhandler)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • ResultHandler对象用来处理查询返回的复杂结果集,
  • 通常用于多表查询
void select(String statement,Object parameter,ResultHandler handler)
  • 查询方法,
  • 参数statement是在配置文件中定义的<select>元素的id,
  • parameter是查询所需的参数,通常是对象或者Map,
  • ResultHandler对象用来处理查询返回的复杂结果集,
  • 通常用于多表查询。

事务方法

方法 描述
void commit() 提交事务。
void rollback() 回滚事务。
void close() 关闭SqlSession对象。

其他方法

方法 描述
Connection getConnection() 获得JDBC的数据库连接对象。
<T> T getMapper(Class<T>type) 返回mapper接口的代理对象,该对象关联了SqlSession对象,开发者可以通过该对象直接调用方法操作数据库,参数typeMapper的接口类型。MyBatis官方手册建议通过mapper对象访问MyBatis

提示

在实际应用中很少会直接使用DriverManager来获取数据库连接,通常都会使用DataSource来获取数据库连接,SqlSessionFactory底层封装了DataSource

9.0 本章要点

  • SqlSessionFactory对象
  • SqlSession对象
  • MyBatis根配置文件详解
  • MyBatis日志信息配置详解
  • Mapper映射文件详解

9.1 MyBatis体系结构

MyBatis的持久化解决方案将用户从原始的JDBC访问中解放出来,用户只需要定义需要操作的SQL语句,无须关注底层的JDBC操作,就可以以面向对象的方式进行持久层操作。底层数据库连接的获取、数据访问的实现、事务控制和数据库连接的关闭等都无须用户关心,从而将应用层从底层的JDBC/JTA API抽取出来。通过配置文件管理JDBC连接,让MyBatis完成持久化访问的实现。
MyBatis中的常用对象有SqlSessionFactorySqlSession

9.1.1 SqlSessionFactory

SqlSessionFactoryMyBatis的关键对象,它是单个数据库映射关系经过编译后的内存镜像。

如何创建SqlSessionFactory实例

SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder对象来获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
每一个MyBatis的应用程序都以个SqlSessionFactory对象的实例为核心。其也是线程安全的,SqlSessionFactory一旦被创建,应该在应用执行期间都存在。在应用运行期间不需要重复创建多次,建议使用单例模式。

SqlSessionFactory常用方法

SqlSessionFactory是创建SqlSession的工厂,SqlSessionFactory的常用方法如下:

方法 描述
SqlSession openSession() 创建SqlSession对象。

8.2 MyBatis入门

MyBatis的用法非常简单,我们只要在Java项目中引入 MyBatis框架,就能以面向对象的方式操作关系数据库

8.2.1 MyBatis下载和安装

下载mybatis

进入mybatis在github上的仓库,进入releases,找到最近发布版本,展开Assets下拉列表,然后点击mybatis-3.5.2.zip超链接,下载连接即可.

mybatis目录结构

下载后,解压mybatis的压缩包,进入解压后的目录,目录结构如下:

D:\Desktop\随书源码\库文件\mybatis-3.5.2
├─lib\
│ ├─ant-1.10.3.jar
│ ├─ant-launcher-1.10.3.jar
│ ├─asm-7.0.jar
│ ├─cglib-3.2.10.jar
│ ├─commons-logging-1.2.jar
│ ├─javassist-3.24.1-GA.jar
│ ├─log4j-1.2.17.jar
│ ├─log4j-api-2.11.2.jar
│ ├─log4j-core-2.11.2.jar
│ ├─ognl-3.2.10.jar
│ ├─slf4j-api-1.7.26.jar
│ └─slf4j-log4j12-1.7.26.jar
├─LICENSE
├─mybatis-3.5.2.jar
├─mybatis-3.5.2.pdf
└─NOTICE

我们需要的是,当前目录下的mybatis-3.5.2.jar这个文件.

提示

由于MyBatis的底层依然是基于JDBC的,因此在应用程序中使用MyBatis执行持久化时同样少不了JDBC驱动。本示例程序底层采用了MySQL数据库,因此还需要将MySQL数据库驱动添加到应用程序的类加载路径中

下载MySQL的Java驱动

进入这个站点,即可下载mysql驱动。在写这篇文章的时候,最新的驱动版本是8.0版本的驱动。8.0版本的驱动支持MySQL5.5开始的后续MySQL版本。下载最新版本即可.

MySQL的Java驱动目录结果

展开/折叠
D:\Desktop\随书源码\库文件\mysql-connector-java-8.0.17
├─build.xml
├─CHANGES
├─INFO_BIN
├─INFO_SRC
├─LICENSE
├─mysql-connector-java-8.0.17.jar
├─README
└─src\

下载log4j

使用log4j来输出日志,如打印运行的SQL命令等.
进入log4j下载站点,然后选择镜像,在镜像的HTTP几个大字下,点击log4j对应的链接,即可下载.

log4j目录结构

展开/折叠
D:\Desktop\随书源码\库文件\apache-log4j-2.13.3-bin
├─LICENSE.txt
├─log4j-1.2-api-2.13.3-javadoc.jar
├─log4j-1.2-api-2.13.3-sources.jar
├─log4j-1.2-api-2.13.3.jar
├─log4j-api-2.13.3-javadoc.jar
├─log4j-api-2.13.3-sources.jar
├─log4j-api-2.13.3.jar
├─log4j-appserver-2.13.3-javadoc.jar
├─log4j-appserver-2.13.3-sources.jar
├─log4j-appserver-2.13.3.jar
├─log4j-cassandra-2.13.3-javadoc.jar
├─log4j-cassandra-2.13.3-sources.jar
├─log4j-cassandra-2.13.3.jar
├─log4j-core-2.13.3-javadoc.jar
├─log4j-core-2.13.3-sources.jar
├─log4j-core-2.13.3-tests.jar
├─log4j-core-2.13.3.jar
├─log4j-couchdb-2.13.3-javadoc.jar
├─log4j-couchdb-2.13.3-sources.jar
├─log4j-couchdb-2.13.3.jar
├─log4j-docker-2.13.3-javadoc.jar
├─log4j-docker-2.13.3-sources.jar
├─log4j-docker-2.13.3.jar
├─log4j-flume-ng-2.13.3-javadoc.jar
├─log4j-flume-ng-2.13.3-sources.jar
├─log4j-flume-ng-2.13.3.jar
├─log4j-iostreams-2.13.3-javadoc.jar
├─log4j-iostreams-2.13.3-sources.jar
├─log4j-iostreams-2.13.3.jar
├─log4j-jcl-2.13.3-javadoc.jar
├─log4j-jcl-2.13.3-sources.jar
├─log4j-jcl-2.13.3.jar
├─log4j-jdbc-dbcp2-2.13.3-javadoc.jar
├─log4j-jdbc-dbcp2-2.13.3-sources.jar
├─log4j-jdbc-dbcp2-2.13.3.jar
├─log4j-jmx-gui-2.13.3-javadoc.jar
├─log4j-jmx-gui-2.13.3-sources.jar
├─log4j-jmx-gui-2.13.3.jar
├─log4j-jpa-2.13.3-javadoc.jar
├─log4j-jpa-2.13.3-sources.jar
├─log4j-jpa-2.13.3.jar
├─log4j-jul-2.13.3-javadoc.jar
├─log4j-jul-2.13.3-sources.jar
├─log4j-jul-2.13.3.jar
├─log4j-liquibase-2.13.3-javadoc.jar
├─log4j-liquibase-2.13.3-sources.jar
├─log4j-liquibase-2.13.3.jar
├─log4j-mongodb2-2.13.3-javadoc.jar
├─log4j-mongodb2-2.13.3-sources.jar
├─log4j-mongodb2-2.13.3.jar
├─log4j-mongodb3-2.13.3-javadoc.jar
├─log4j-mongodb3-2.13.3-sources.jar
├─log4j-mongodb3-2.13.3.jar
├─log4j-slf4j-impl-2.13.3-javadoc.jar
├─log4j-slf4j-impl-2.13.3-sources.jar
├─log4j-slf4j-impl-2.13.3.jar
├─log4j-slf4j18-impl-2.13.3-javadoc.jar
├─log4j-slf4j18-impl-2.13.3-sources.jar
├─log4j-slf4j18-impl-2.13.3.jar
├─log4j-spring-cloud-config-client-2.13.3-javadoc.jar
├─log4j-spring-cloud-config-client-2.13.3-sources.jar
├─log4j-spring-cloud-config-client-2.13.3.jar
├─log4j-taglib-2.13.3-javadoc.jar
├─log4j-taglib-2.13.3-sources.jar
├─log4j-taglib-2.13.3.jar
├─log4j-to-slf4j-2.13.3-javadoc.jar
├─log4j-to-slf4j-2.13.3-sources.jar
├─log4j-to-slf4j-2.13.3.jar
├─log4j-web-2.13.3-javadoc.jar
├─log4j-web-2.13.3-sources.jar
├─log4j-web-2.13.3.jar
├─NOTICE.txt
└─RELEASE-NOTES.md

MyBatis的数据库操作入门

项目结构

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
D:\Desktop\随书源码\Spring+Mybatis企业应用实战(第2版)\codes\08\MyBatisQs
├─src\
│ ├─log4j.properties
│ ├─mybatis-config.xml
│ └─org\
│ └─fkit\
│ ├─domain\
│ │ ├─crateDatabase.sql
│ │ ├─createTable.sql
│ │ ├─test.sql
│ │ ├─User.java
│ │ └─user_inf.sql
│ ├─mapper\
│ │ └─UserMapper.xml
│ └─test\
│ └─MyBatisTest.java
└─WebContent\
├─META-INF\
│ └─MANIFEST.MF
└─WEB-INF\
├─lib\
│ ├─commons-logging-1.2.jar
│ ├─log4j-1.2.17.jar
│ ├─log4j-api-2.3.jar
│ ├─log4j-core-2.3.jar
│ ├─mybatis-3.4.5.jar
│ ├─mysql-connector-java-5.1.44-bin.jar
└─web.xml

引入jar文件到lib目录

引入mybatis的jar文件

进入mybatis目录,使用如下copy命令把mybatisjar包复制到web项目的lib目录中.

1
copy mybatis-3.5.2.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib

复制效果如下:

D:\Desktop\随书源码\库文件\mybatis-3.5.2>copy mybatis-3.5.2.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
已复制         1 个文件。

引入mysql驱动

进入解压后的mysql驱动目录,打开cmd,输入如下命令进行复制:

1
copy mysql-connector-java-8.0.17.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib

复制效果如下:

D:\Desktop\随书源码\库文件\mysql-connector-java-8.0.17>copy mysql-connector-java-8.0.17.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
已复制         1 个文件。

引入log4j的jar包

解压下载好的log4j压缩包,我发现有好多jar包啊,官网上给出的消息如下:

Using Log4j on your classpath
To use Log4j 2 in your application make sure that both the API and Core jars are in the application’s classpath. Add the dependencies listed below to your classpath.

log4j-api-2.13.3.jar
log4j-core-2.13.3.jar

You can do this from the command line or a manifest file.

所以,复制log4j-api-版本号.jar,和log4j-core-版本号.jar这两个文件到web项目的lib目录下即可.

1
2
copy log4j-api-2.13.3.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
copy log4j-core-2.13.3.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
D:\Desktop\随书源码\库文件\apache-log4j-2.13.3-bin>copy log4j-api-2.13.3.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
已复制         1 个文件。

D:\Desktop\随书源码\库文件\apache-log4j-2.13.3-bin>copy log4j-core-2.13.3.jar E:\workspacne_JDK8Tomcat8.5\MyBatisTest\WebContent\WEB-INF\lib
已复制         1 个文件。

创建数据库 mybatis

1
2
# 创建一个数据库,指定数据库的字符为真正的utf-8编码
create database `mybatis` default character set utf8;

创建数据表 tb_user

1
2
3
4
5
6
7
8
9
10
11
# 使用刚才创建的数据库
use mybatis;
# 创建表格tb_user
drop table if exists tb_user;
create table tb_user(
id int(11) not null auto_increment,
name varchar(18) default null,
sex char(2) default null,
age int(11) default null,
primary key (id)
);

创建成功效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql> # 创建一个数据库,指定数据库的字符为真正的utf-8编码
create database `mybatis` default character set utf8;
Query OK, 1 row affected (0.02 sec)

mysql> # 使用刚才创建的数据库
use mybatis;
# 创建表格tb_user
drop table if exists tb_user;
create table tb_user(
id int(11) not null auto_increment,
name varchar(18) default null,
sex char(2) default null,
age int(11) default null,
primary key (id)
);
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.04 sec)

好了,有了数据表,现在来创建对应的持久化类.

创建持久化类 User.java

持久化对象 PO

在所有的ORM框架中都有一个非常重要的媒介:PO(持久化对象)。持久化对象的作用就是完成持久化操作,简单地说,就是通过持久化对象来对数据库执行增、删、改的操作,以面向对象的方式操作数据库
应用程序无须直接访问数据库,甚至无须理会底层数据库采用何种数据库,应用程序只需创建、修改、删除持久化对象即可;与此同时**MyBatis则负责把这种操作转换为对指定数据库表的操作**。
MyBatis完全采用普通的Java对象作为持久化对象使用

User.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
public class User
implements Serializable
{
private static final long serialVersionUID = 1L;
// 用户标识
private Integer id;
// 用户姓名
private String name;
// 用户性别
private String sex;
// 用户年龄
private Integer age;
// 无参数构造器
public User()
{
super();
}
// 有参数构造器
public User(String name, String sex, Integer age)
{
super();
this.name = name;
this.sex = sex;
this.age = age;
}
// 此处省略getter和setter方法,请自己补上
@Override
public String toString()
{
return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}

POJO

仔细看上面这个类的代码,会发现这个类与普通的JavaBean没有任何区别。实际上,MyBatis直接采用了POJO(普通的、传统的Java对象)作为持久化类,这就是MyBatis被称非低侵入式设计的原因。 MyBatis不要求持久化类继承任何父类,或者实现任何接口 ,这样可保证代码不被污染。

UserMapper.xml 映射持久化类和数据表

MyBatis是通过XML文件去完成持久化类和数据库表之间的映射关系的.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.UserMapper">
<!-- id="save"是唯一的标示符 -->
<!-- parameterType属性指明插入时使用的参数类型,也就是PO类的全路径 -->
<!-- useGeneratedKeys="true"表示使用数据库的自动增长策略 -->
<insert
id="save"
parameterType="org.fkit.domain.User"
useGeneratedKeys="true"> insert into tb_user(name,sex,age) values(#{name},#{sex},#{age})
</insert>
</mapper>

mapper标签的namespace属性

上面的XML配置中定义了一条insert语句,详细解释如下
<mapper namespace="org.fkit.mapper.UserMapper">:
为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+SQL映射文件名,这样就能够保证namespace的值是唯一的,例如namespace="org.fkit.mapper.UserMapper"就是org.fkit.mapper(包名)+UserMapper(UserMapper.xml去除后缀后的文件名)

mapper标签的子标签insert详解

1
2
3
4
5
<insert
id="save"
parameterType="org.fkit.domain.User"
useGeneratedKeys="true"> insert into tb_user(name,sex,age) values(#{name},#{sex},#{age})
</insert>

id属性

insert标签中编写了SQL插入语句,设置insert标签的id属性值为saveid属性值必须是唯一的,不能够重复

parameterType属性

使用parameterType属性指明插入时使用的参数类型,属性值设置为持久化对象的全限定名

useGeneratedKeys属性

使用useGeneratedKeys="true"表示使用数据库的自动增长策略,这需要底层数据库的支持。

insert语句

insert标签中只有一条标准的insert语句,用来向tb_user表插入一条数据,#{name}表示取参数中的对象的name属性值。

mybatis-config.xml Mybatis根配置文件

对于MyBatis来说,现在还不知道需要连接哪个数据库,以及连接数据库时所用的连接池用户名密码等详细信息。这些信息对于所有的持久化类都是通用的,MyBatis把这些通用信息称为根配置信息,根配置信息需要使用配置文件指定。
MyBatis根配置文件默认被命名为mybatis-config.xml,应用程序运行时需要先加载该文件.

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
<?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">
<!-- XML 配置文件包含对 MyBatis 系统的核心设置 -->
<configuration>
<!-- 指定 MyBatis 所用日志的具体实现 -->
<settings>
<setting
name="logImpl"
value="LOG4J"/>
</settings>
<environments default="mysql">
<!-- 环境配置,即连接的数据库。 -->
<environment id="mysql">
<!-- 指定事务管理类型,type="JDBC"指直接简单使用了JDBC的提交和回滚设置 -->
<transactionManager type="JDBC"/>
<!-- dataSource指数据源配置,POOLED是JDBC连接对象的数据源连接池的实现。 -->
<dataSource type="POOLED">
<property
name="driver"
value="com.mysql.jdbc.Driver"/>
<!-- 数据库的URL -->
<property
name="url"
value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
<!-- 数据库的账户 -->
<property
name="username"
value="root"/>
<!-- 数据的密码 -->
<property
name="password"
value="root"/>
</dataSource>
</environment>
</environments>
<!-- mappers告诉了MyBatis去哪里找持久化类的映射文件 -->
<mappers>
<mapper resource="org/fkit/mapper/UserMapper.xml"/>
</mappers>
</configuration>

配置文件详解

XML文件声明

MyBatis配置文件是一个XML文件,该文件第一行是XML文件声明,指定该XML文件的版本和存储该文件所用的字符集:

1
<?xml version="1.0" encoding="UTF-8" ?>

根元素 configuration

MyBatis配置文件的根元素是configuration,

settings子元素
  • 根元素configuration中有settings子元素,该元素有很多子元素,本示例只是配置了日志信息,之后可以在控制台看到输出的SQL语句,其在调试中非常有用。
environments子元素
  • 根元素configuration中还有environments子元素,用来配置MyBatis的环境,即连接的数据库,该子元素用于将SQL映射应用于多种数据库中。每个数据库对应一个SqlsessionFactory,可以配置多种环境,但只能为SqlsessionFactory实例选择一个环境,default属性表示选择的环境。
environment子元素
  • environments元素的environment子元素用于配置一个环境,
    • environmenttransactionManager子元素用来配置MyBatis当中的事务管理,JDBC属性表示直接简单使用JDBC的提交和回滚设置。
    • environment的**datasource子元素用来配置数据源**,MyBatis并不推荐采用DriverManager来连接数据库,而是推荐使用薮据源来管理数据库连接,这样能保证最好的性能。
      • datasource元素依次有很多property子元素,这些property子元素用于配置MyBatis连接数据库的必要信息,如连接数据库的驱动、URL、用户名、密码等信息

mapper子元素

  • 根元素configuration中还有mappers子元素,它可以支持多个mapper子元素,每个mapper子元素用于指定一个持久化配置文件

数据源介绍

数据源是一种用来提高数据库连接性能的常规手段,数据源会负责维持一个数据库连接池,当程序创建数据源实例时,系统会一次性地创建多个数据库连接,并把这些数据库连接保存在连接池中。当程序需要进行数据库访问时,无须重新获得数据库连接,而是从连接池中取出一个空闲的数据库连接,当程序使用数据库连接访问数据库结束后无须关闭数据库连接,而是将数据库连接归还给连接池即可。通过这种方式,就可避免频繁地获取数据库连接、关闭数据库连接所导致的性能下降

MyBatisTest.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
public class MyBatisTest {
public static void main(String[] args)
{
// 创建Session实例
SqlSession sqlSession = null;
try (
// 读取mybatis-config.xml文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");)
{
// 读取配置文件,初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession();
// 创建User对象
User user = new User("admin", "男", 26);
// 插入数据
sqlSession.insert("org.fkit.mapper.UserMapper.save", user);
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
try
{
// 关闭sqlSession
if (sqlSession != null)
sqlSession.close();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}

上面持久化操作的代码非常简单。程序先创建一个User对象,再使用SqlSessioninsert()方法来保存User对象即可,这是完全对象化的操作方式,可以说非常简单明了。当Java程序以面向对象的方式来操作持久化对象时,MyBatis负责将这种操作转换为底层SQL操作。

log4j.properties 显示执行的SQL语句

执行持久化操作之前,为了查看控制台输出的SQL语句,需要加入日志框架log4j的相关jar包,在CLASSPATH下增加一个log4.properties文件:

# 全局的日志配置
log4j.rootLogger=ERROR, stdout
# Mybatis的日志配置:追踪SQL运行结果
log4j.logger.org.fkit.mapper.UserMapper=DEBUG
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] %m%n

运行效果

运行MyBatisTest类的main()方法,运行完成后,可以看到mybatis数据库中的TB_USER表中包含了User实例对应的记录,如下图所示:
这里有一张图片
控制台输出

1
2
3
DEBUG [main] ==>  Preparing: insert into tb_user(name,sex,age) values(?,?,?) 
DEBUG [main] ==> Parameters: admin(String), 男(String), 26(Integer)
DEBUG [main] <== Updates: 1

使用MyBatis持久化操作步骤

在执行sqlSession.insert("org.fkit.mapper.UserMapper.save", user);之前,先要获取SqlSession对象。PO只有在SqlSession的管理下才可完成数据库访问。为了使用MyBatis进行持久化操作,通常需要执行如下操作步骤

  1. 开发持久化类PO和编写持久化操作的Mapper.xml,在其中定义要执行的SQL语句
  2. 获取SqlSessionFactorySqlSessionFactory是数据库编译后的内存镜像,通常一个应用对应一个SqlSessionFactory对象。SqlSessionFactory对象通过加载mybatis-config.xml配置文件生成.
  3. 获取SqlSessionSqlSessionSqlSessionFactory工厂产生,对PO的操作必须在SqlSession的管理下才能同步到数据库。
  4. 用面向对象的方式操作数据库。
  5. 关闭事务,关闭SqlSession

MyBatis相较JDBC的优点

MyBatis相较JDBC有如下两个显著优点

  • 只需要在Mapper.xml配置文件中编写SQL语句,在应用程序中就可以采用PO方式来访问数据库。
  • JDBC访问过程中大量的checked异常被包装成MyBatisRuntime异常,从而不再要求程序必须处理所有异常。

8.1.4 MyBatis概述

MyBatis可以使用简单的XML或注解进行配置和原始映射,JavaPOJO(Plain old Java Objects,普通的Java对象)映射成数据库中的记录

MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离岀来,配置在配置文件中,以实现SQL的灵活配置。这样做的好处是:SQL与程序代码分离,做到可以在不修改程序代码的情况下,直接在配置文件中修改SQL

纵观目前主流的ORM,无论 Hibernate还是JPA,都对数据库结构提供了较为完整的封装,提供了从POJO到数据库表的全套映射机制。程序员往往只需定义好POJO到数据库表的映射关系,即可通过ORM提供的方法完成持久层操作。程序员甚至不需要熟练掌握SQL,Hibernate,JPA会根据制定的存储逻辑,自动生成对应的SQL并调用JDBC接口加以执行。

Hibernate和MyBatis的区别

对于具体的数据操作, Hibernate会自动生成SQL语句,而 MyBatis则并不会为程序员在运行期间自动生成SQL。具体的SQL需要程序员编写,然后通过映射配置文件,将SQL所需的参数及返回的结果字段映射到指定POJO

8.1.3 流行的ORM框架简介

目前流行的ORM框架有如下这些产品:

JPA

JPA本身只是一种ORM规范,并不是ORM产品。它是 Java EE规范制定者向开源世界学习的结果。相对于其他开源ORM框架,JPA的最大优势在于它是官方标准,因此具有通用性。如果应用程序是面向JPA编程,那么应用程序就可以在各种ORM框架之间自由切换。

Hibernate

目前最流行的开源ORM框架,已经被选为JBoss的持久层解决方案。整个Hibernate项目也一并投入了JBoss的怀抱,而JBoss又加入了Redhat组织。因此,Hibernate属于RedHat组织的一部分。Hibernate灵巧的设计、优秀的性能,以及丰富的文档,都是其风靡全球的重要因素.

MyBatis

MyBatis(早期名称是iBATIS)。是Apache软件基金组织的子项目。与其称它是种ORM框架,不如称它是一种“SQL Mapper”框架,它是一种“半自动化”的ORM的实现。曾经在Java EE开发中扮演非常重要的角色,但是其并不支持纯粹的面向对象操作,它允许开发人员直接编写SQL语句,更加灵活。

8.1.2 基本映射方式

ORM工具提供了持久化类和数据表之间的映射关系,通过这种映射关系的过渡,程序员可以很方便地通过持久化类实现对数据表的操作。实际上,所有的ORM工具大致都遵循相同的映射思路。ORM有如下几条基本映射关系

数据表 映射 类

持久化类被映射到一个数据表。程序使用这个持久化类来创建实例、修改属性、删除实例时,系统自动会转换为对这个表进行CRUD操作。图8.2显示了这种映射关系。

这里有一张图片

图8.2数据表对应Model

ORM管理的持久化类(就是一个普通Java类)对应一个数据表,只要程序对这个持久化类进行操作,系统就可以将其转换成对对应数据库表的操作

数据表的行 映射 对象

持久化类会生成很多实例(对象),每个实例就对应数据表中的一行记录当程序在应用中修改持久化类的某个实例时,ORM工具会将其转换成对对应数据表中特定行的操作。每个持久化对象对应数据表的一行记录的示意图如图8.3所
这里有一张图片

图8.3数据表中的记录行对应持久化对象

数据表的列(字段) 映射 对象的属性

当程序修改某个持久化对象的指定属性时,ORM会将其转换成对对应数据表中指定数据行、指定列的操作。数据表的列被映射到对象属性的示意图如图8.4所示

这里有一张图片

图8.4数据表中的列对应对象的属性

基于这种基本的映射方式,ORM工具可完成对象模型和关系模型之间的相互映射。由此可见,ORM框架中,持久化对象是一种媒介,应用程序只需操作持久化对象,ORM框架则负责将这种操作转换为底层数据库操作这使得开发者能以面向对象的思维操作关系数据库

8.1 ORM和MyBatis

目前流行的编程语言,例如JavaC#等,都是面向对象的编程语言;而目前主流的数据库产品,例如OracleDB2等,依然是关系数据库编程语言和底层数据库的发展不协调,催生岀了ORM框架,ORM框架可作为面向对象编程语言和数据库之间的桥梁
确切地说,MyBatis并不完全是一种ORM框架,它的设计思想和ORM相似,只是它允许开发人员直接编写SQL语句,使得访问数据库更加灵活,更准确地说,它应该是一种SQL Mapping框架

8.1.1 对象/关系数据库映射(ORM)

ORM的全称是 Object/Relation Mapping,即对象/关系数据库映射。可以将ORM理解成一种规范,它概述了这类框架的基本特征,完成面向对象的编程语言到关系数据库的映射。当ORM框架完成映射后,程序员既可以利用面向对象程序设计语言的简单易用性,又可以利用关系数据库的技术优势。因此可以把ORM当成应用程序和数据库的桥梁
ORM可以把关系数据库包装成面向对象的模型

最终面向对象数据库会取代关系数据库,ORM工具会逐渐消亡。但只要依然采用面向对象程序设计语言,底层依然采用关系数据库,中间就少不了ORM工具。
采用ORM框架之后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象(例如创建、修改、删除等),而ORM框架则将这些面向对象的操作转换成底层的SQL操作

ORM工具的作用

ORM工具的唯一作用就是:把对持久化对象的保存、修改、删除等操作,转换成对数据库的操作。由此,程序员可以以面向对象的方式操作持久化对象,ORM框架则负责将相关操作转换成对应的SQL(结构化査询语言)操作

这里有一张图片