此博客用于个人学习,来源于ssm框架的书籍,对知识点进行一个整理。
1.1 持久层的概念和 Mybatis 的特点:
持久层可以将业务数据存储到磁盘,具备长期储存能力,只要磁盘不损坏(大部分的重要数据都有对应的备份机制),在断电或者其他情况下,重新开启系统仍然可以读取这些数据。一般执行持久层任务的都是数据库系统,持久层可以使用巨大的磁盘空间,但是它的缺点是比较慢。在这样的场景下考虑使用 Redis(NOSQL) 处理它。
Java 互联网技术可以通过 Mybatis 框架访问数据库。
Mybatis 的特点主要有3点:
- 不屏蔽 SQL,可以更加精确地定位 SQL 语句。
- 提供强大,灵活的映射机制,方便 Java 开发者使用。
- 只需要一个接口和一个 XML 就能创建映射器,进一步简化我们的工作,使得很多框架 API 在 Mybatis 中消失。
1.2 Mybatis 的核心组件:
Mybatis 的核心组件分为四个部分:
- SqlSessionFactoryBuilder(构造器):会根据配置或者代码来生成 SqlSessionFactory ,采用的是分布构建的 Builder 模式。
- SqlSessionFactory(工厂接口):生成 SqlSession ,使用的是工厂模式。
- SqlSession(会话):一个既可以发送 SQL 执行返回结果,也可以获取 Mapper 的接口。
- SQL Mapper(映射器):由一个 Java 接口和 XML 文件(或注解)构成,需要给出对应的 SQL 和映射规则。
1.3 SqlSessionFactory(工厂接口):
使用 Mybatis 框架的第一步就是构建 SqlSessionFactory。在 MyBatis 中,既可以通过配置的 XML 文件,也可以通过 Java 代码的形式生成 SqlSessionFactory。推荐使用 XML 的方式生成,而生成的 SqlSessionFactory 的作用是生产 Mybatis 的核心接口对象 SqlSession。
在 Mybatis 中的 XML 文件分为两类,一类是基础配置文件,通常只有一个,主要是配置一些基本的上下文参数和运行环境;另外一类可以配置映射关系,SQL,参数等信息。
首先,先看一份基础配置文件,命名为 config.xml 。
<?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">
<!--mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接源(连接池)-->
<dataSource type="POOLED">
<!--配置数据库的四个信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 告知 mybatis 映射配置的位置 -->
<mappers>
<mapper resource="com/itheima/dao/RoleMapper.xml"/>
</mappers>
</configuration>
其中,<environment> 用于配置数据库的信息,里面的 <transactionManager> 是配置事务管理器,这里采用的是 MyBatis 的 JDBC 管理器方式,然后采用 <dataSource> 元素配置数据库。
<Mapper> 元素代表引入的那些映射器。
有了配置文件,就可以通过简短的代码来生产 SqlSessionFactory ,代码如下:
SqlSessionFactory sqlSessionFactory = null;
String resource = "config.xml";
InputStream inputStream;
try{
inputStream = Resources.getRescourceAsStream(resource);
SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch(IOException e){
e.printStackTrace();
}
首先读取 config.xml 文件,然后通过 SqlSessionFactoryBuilder 的 Builder 方法去创建 SqlSessionFactory。
1.4 SqlSession:
SqlSession 的作用类似于一个 JDBC 中的 Connection 对象,代表着一个连接资源的启用。具体而言,它的作用有以下三个:
- 获取 Mapper 接口。
- 发送 SQL 给数据库。
- 控制数据库事务。
有了 SqlSessionFactory ,就可以创建 SqlSession。
SqlSession sqlSession = SqlSessionFactory.openSession();
SqlSession 只是一个门面接口,它有很多方法,可以直接发送 SQL。
下面是 SqlSession 控制数据库事务的方法,代码如下:
//定义SqlSession
SqlSession sqlSession = null;
try{
//打开SqlSession会话
sqlSession = SqlSessionFactory.openSession();
//程序运行代码。。。
...
//提交事务
sqlSession.commit();
}catch(Exception e){
//回滚事务
sqlSession.rollback();
}finally{
//在finally中确保资源被顺利关闭
if(sqlSession != null){
sqlSession.close();
}
}
这里使用 commit 方法提交事务,或者使用 rollback 方法回滚事务,因为它代表一个数据库的连接资源,使用后要及时关闭它,如果不关闭,那么数据库的连接资源很快就会被耗费光,所以最后用 finally 语句保证其顺利关闭。
由于 SqlSession 的获取 Mapper 接口和发送 SQL 的功能需要先实现映射器的功能,而映射器接口也可以实现发送 SQL 的功能。
1.5 映射器:
映射器是 MyBatis 中最重要,最复杂的组件,它由一个接口和对应的 XML 文件(或注解)组成,可以配置以下规则:
- 描述映射规则。
- 提供 SQL 语句,并可以配置 SQL 参数类型,返回类型,缓存刷新等信息。
- 配置缓存。
- 提供动态 SQL。
映射器的实现方式有两种:XML 文件形式和注解形式,作用是将 SQL 查询的结果映射为一个 POJO,或者是将 POJO 的数据插入到数据库中,并定义一些关于缓存等的重要内容。先定义一个 POJO类,用于企业中也可以是用户类。
public class Role {
private Long id;
private String roleName;
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
3.5.1 用 XML 实现映射器:
用 XML 定义映射器分为两个部分:接口和 XML。先定义一个接口,代码如下:
public interface RoleMapper{
public Role getRole(Long id);
}
在用 XML 方式创建 SqlSession 的配置文件中有这样一行代码:
<mapper resource="com/itheima/dao/RoleMapper.xml"/>
它的作用就是引入一个 XML 文件,用 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="com.itheima.dao.RoleMapper">
<!--配置查询所有操作-->
<select id="getRole" parameterType="long" resultType="com.itheima.domain.Role">
select id,role_name as rolename,note from t_role where id = #{id}
</select>
</mapper>
- <mapper> 中的属性 namespace 所对应的是一个接口的全限定名,于是 MyBatis 上下文就可以通过它找到对应的接口。
- <select> 表明是一条查询语句,属性 id=“getRole” 对应接口的方法名,属性 parameterType=“long” 说明传递 SQL 的是一个 long 型的参数,而 resultType=“com.itheima.domain.Role” 表明返回的是一个 role 类型的返回值。
- #{id} 是传递进去的参数。
用了这两个文件,就完成了一个映射器的定义,只要 SQL 返回的列名能与 POJO 对应起来就可以自动映射。
3.5.2 注解实现映射器:
这种方式实现映射器许哟啊一个接口就可以通过 MyBatis 的注解来注入 SQL,代码如下:
public interface RoleMapper2{
@Select("select id,role_name as rolename,note from t_role where id = #{id}")
public Role getRole(Long id);
}
这与 XML 方式创建映射器完全等同,如果它和 XML 方式同时定义时,XML 方式将覆盖掉注解方式,而且在工作中,SQL 的复杂度远远超过我们现在看到的 SQL,如果把这种复杂的 SQL 语句放入注解中,会使代码的可读性严重下降,不利于日后的维护和修改。
3.5.3 SqlSession 发送 SQL:
有了映射器就可以通过 SqlSession 发送 SQL 了,我们以 getRole 为例。
Role role = (Role)sqlSession.selectOne("com.itheima.mapper.RoleMapper.getRole",1L);
selectOne 表示使用查询并且返回一个对象,而参数是一个 String 对象和一个 Object 对象,这里是一个 long 参数,long 参数是它的主键。
3.5.4 用 Mapper 接口发送 SQL:
sqlSession 还可以获取 Mapper 接口,通过 Mapper 接口发送 SQL,代码如下:
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(1L);
通过 sqlSession 的 getMapper 方法来获取一个 Mapper 接口,就可以调用它的方法了。
3.5.5 对比两种发送 SQL 方式:
建议采用第二种,也就是获取 Mapper 接口再发送的方式,理由如下:
- 通过 Mapper 可以消除 SqlSession 带来的功能性代码,提高可读性,而 SqlSession 发送 SQL,需要一个 SQL id 去匹配 SQL,而且使用 Mapper 更能体现业务的逻辑。
- 使用 roleMapper.getRole(1L) 语法,IDE 会提示错误和校验,而使用 sqlSession.selectOne(“com.itheima.mapper.RoleMapper.getRole”,1L) 语法,只有在运行中才能知道是否会产生错误。