目录
1、持久层的概念和MyBatis的特点
2、准备MyBatis环境
3、MyBatis的核心组件
4、SqlSessionFactory(工厂接口)
4.1、使用XML构建SqlSesionFactory
4.2、使用Java构建SqlSesionFactory
5、SqlSession(会话)
6、映射器
6.1 用XML实现映射器
6.2 用注解实现映射器
持久层可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏,或断电,或其他情况下,重新开启系统任然可以读取这些数据。一般执行持久任务的都是数据库系统,持久层可以使用巨大的磁盘空间,也比较廉价,缺点就是比较慢。当然慢是针对内存而言的,在一般的系统中运行是不存在问题的,比如内存管理系统,但是在互联网的秒杀场景下,每秒都需要执行成千上万次数据操作,慢是不能承受的,极有可能宕机,这种情况下考虑使用Redis(NoSQL)处理它。
Java互联网应用通过MyBatis框架访问数据库:
MyBatis最大的成功主要有3点:
一个讲解较入门的MyBatis参考文档:http://www.mybatis.org/mybatis-3/zh/getting-started.html
Maven仓库地址:https://mvnrepository.com/
MyBatis所需的包和源码下载地址:https://github.com/mybatis/mybatis-3/releases
我们来看下MyBatis的“表面现象”——组件。
MyBatis的核心组件分为4部分:
MyBatis核心组件之间的关系:
使用MyBatis首先是使用配置或代码去生产SqlSessionFactory,而MyBatis提供了构造器SqlSessionFactoryBuilder。
它提供了一个类org.apache.ibatis.session.Cobfiguration作为引导,采用Builder模式。具体的分步是在Configuration类里面完成的。
在MyBatis中,既可以通过读取配置的XML文件的形式生产SqlSessionFactory,也可以通过Java代码的形式去生产SqlSessionFactory。这里建议使用XML配置的方式。当配置了XML或提供程序后,MyBatis会读取 配置文件,通过Configuration类对象构建整个MyBatis的上下文。
【注意】SqlSessionFactory接口存在两个实现类:SqlSessionManager和DefaultSqlSessionFactory。常用DefaultSqlSessionFactory去实现,而SqlSessionManager使用在多线程环境中,它的具体实现依靠DefaultSqlSessionFactory。它们之间关系:
每个基于MyBatis的应用都是一个以SqlSessionFactory的实例为中心的,而SqlSessionFactory唯一的作用就是生产MyBatis的核心接口对象SqlSession,所以它的责任是唯一的。这里,我们往往采用单例模式处理它,下面将讨论使用XML文件配置方式和Java代码方式去生产SqlSessionFactory的方法。
MyBatis的XML文件分为两类:
【1】基础配置文件
用于配置基本上下文参数和运行环境;
【2】映射文件
用于配置映射关系、SQL、参数等信息
MyBatis的基础配置文件:
我们描述一下MyBatis的基础配置文件:
方式1:引入外部的属性文件;
方式2:在其子标签
方式3:代码传递方式传递参数
有了基础配置文件,我们用一段程序生成SqlSessionFactory:
SqlSessionFactory sqlSessionFactory = null;
String resource = "mybatisConfig.xml";
InputStream inputStream;
try{
//读取mybatisConfig.xml文件
inputStream = Resource.getResourceAsStream(resource);
//通过SqlSessionFactoryBuilder的build方法去创建SqlSessionFactory。
//采用Build模式隐藏了详细的构建细节
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch(IOException e){
e.printStackTrace();
}
采用XML创建的形式,信息在配置文件中,利于后期维护和修改,避免重新编译程序。
我们不建议使用这种方式去构建SqlSesionFactory,还是了解一下Java构建SqlSesionFactory。
//数据库连接池信息
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver(”com.mysql.jdbc.Driver”);
dataSource.setUsername(”root”);
dataSource.setPassword(”123456”) ;
dataSource.setUrl(”jdbc:mysql://localhost:3306/ssm”);
dataSource.setDefaultAutoCommit(false);
//采用MyBatis的JDBC事务方式
TransactionFactory transactionFactory = new JdbcTransactionFactory() ;
Environment environment = new Environment(”development” transactionFactory, dataSource);
//创建onf工guraton象
Configuration configuration = new Configuration(environment);
//注册一个MyBat工s上下文别名
configuration.getTypeAliasRegistry( ).registerAlias (”role", Role.class);
//加入一个映射器
configuration.addMapper(RoleMapper.class);
//使用SqlSessionFactoryBuilder构建SqlSessionFactory
SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration) ;
return SqlSessionFactory ;
它的功能和XML方式实现的功能是一致的,只是方式不一样。但是代码冗长,如果发生系统修改,有可能需要重新编译代码才能继续。
在MyBatis中,SqlSession是其核心接口。在MyBatis中有两个实现类:DefaultSqlSession和SqlSessionManager。
DefaultSqlSession是单线程使用的,而SqlSessionManager在多线程环境下使用。
SqlSession的作用类似一个JDBC中的Connection对象,代表着一个连接资源的启用。
具体而言,SqlSession的作用有3个:
创建SqlSession:
SqlSession sqlSession = sqlSessionFactory.openSession();
注意SqlSession只是一个门面接口,在MyBatis中,真正在干活的是Executor。
SqlSession控制数据库事务的方法:
//定义SqlSession
SqlSession sqlSession = null;
try{
//打开SqlSession会话
sqlSession = SqlSessionFactory.openSession();
//....
sqlSession.commit();//提交事务
} catch(Exception e){
sqlSession.rollback();//回滚事务
} finally{
if(null != sqlSession){
sqlSession.closer();
}
}
这里使用commit提交事务,或rollback回滚事务。因为SqlSession代表着一个数据库的连接资源,使用后要及时关闭它,如果不关闭,则数据库链接资源将会很快耗费光,影响系统性能。
映射器是MyBatis中最重要、最复杂的组件,它由一个Mapper接口和对应的XML文件(或注解)组成。它可以配置以下内容:
这里我们使用两种实现映射器的方式:【1】XML配置方式;【2】注解方式
定义一个POJO类:
public class SysRole {
private Integer id;
private String name;
private String description;
private Date createTime;
private Date updateTime;
/*省略setter和getter方法*/
}
映射器的主要作用就是讲SQL查询到的结果映射为一个POJO类,或将POJO的数据插入到数据库中,并定义一些关于缓存等。这里需要注意所定义的POJO类中变量需要与数据库中表的字段相对应。
使用XML方式定义映射器包括:Mapper接口和XML配置文件。
首先定义一个映射器接口:
/**
* 映射器接口
*/
public interface SysRoleMapper {
/*===========================[1]最基础的操作===========================*/
/*[1.1]新增一条角色------->自定义主键*/
public int insertRole(SysRole sysRole);
/*[1.2]新增一条角色------->自增主键*/
public int insertRole2(SysRole sysRole);
/*[2]删除一条角色*/
public int deleteRole(Integer id);
/*[3]修改一条角色*/
public int updateRole(SysRole sysRole);
/*[4]查询一条角色*/
public SysRole getRole(Integer id);
/*===========================[2]传递多个参数===========================*/
/*[1]通过角色名获取整个角色列表*/
public List findRolesByMap(Map map);
/*
*[2]注解方式传递多个参数
* 注解@Param(),定义映射器的参数名称
* 传递参数的个数<=5时,最贱传参方式
* 传递参数的个数>5时,不推荐使用,建议使用Java Bean的方式
*/
public List findRolesByAnnotation(@Param("name") String name,
@Param("description") String description);
/*
*[3]Java Bean的方式传递多个参数
*/
public List findRoleByBean(SysRole sysRole);
/*
*[4]混合使用的方式传递多个参数
*可通过角色名称和描述进行查询,同时还需要支持分页
*须明确参数的合理性
*/
public List findRoleByMix(@Param("name") String name,
@Param("page") PageParams pageParams);
/*测试分页参数RowBounds*/
public List findRoleByRowBounds(@Param("name") String name,
@Param("description") String description, RowBounds rowBounds);
}
在mybatis的基础配置文件mybatisConfig.xml中,如下这个代码段所示:引入了映射器配置,它的目的就是引入Mapper接口对应的XML映射文件。
在基础配置文件中,引入mybatis的映射器后,我们需要使用XML文件来创建一个映射器,实际上这个映射文件和Mapper接口相对应,主要用于通过SQL语句来操作数据库 :
select LAST_INSERT_ID()
insert into sys_role(name,description,createTime,updateTime)
values (#{name}, #{description}, #{createTime},#{updateTime})
insert into sys_role(name,description)
values (#{name}, #{description})
delete from sys_role where id = #{id}
update sys_role set name = #{name},description = #{description}
where id = #{id}
id,name,description
【注意】我们并没有配置SQL执行后和role的对应关系,它是如何映射的呢?其实这里采用的是一种被称为自动映射的功能,MyBatis在默认情况下提供自动映射,只要SQL返回的列名能和POJO对应起来即可。这里SQL返回的列名id和note是可以和之前定义的POJO的属性对应起来的,而表里的列role_name通过SQL别名的改写,使其成为roleName,也是和POJO对应起来的,所以此时MyBatis就可以把SQL查询的结果通过自动映射的功能映射成为一个POJO。
使用注解方式实现映射器,只需一个接口即可,可以通过MyBatis的注解来注入SQL。
publis interface SysRoleMapper2{
@Select("select id,role_name as roleName from sys_role where id = #{id}")
public SysRole getRole(int id);
}
注解方式等同于XML方式创建映射器,但是在复杂的SQL语句上,注解方式的缺点就暴露出来,即注释内容过多而影响代码可读性。如果使用动态SQL,判断字段空作为查询条件,需要加入其他逻辑,使得注解更为复杂,不利后期维护和修改。