【Mybatis】(2)认识核心组件
(1)Mybatis基本介绍
互联网应用可以通过Mybatis框架访问数据库
Mybatis的优点有3个:
- 不屏蔽SQL:可以在xml配置文件中对SQL语句进行修改和优化
- 有强大灵活的映射机制:在xml中配置中把sql语句和执行结果映射到dao层的方法中
- 提供了使用Mapper的接口编程:只要一个接口和XML就能创建映射器,不需要实体类,简化了工作
(2)核心组件基本介绍
- SQLSessionFactoryBuilder(构造器):根据配置文件(一般都是mybatis-config.xml)或者代码生成SQLSessionFactory(工厂接口),用到【建造者模式】
- SQLSessionFactory(工厂接口):生成SQLSession,用到【工厂模式】,看做是数据库连接池
- SQLSession(会话):可以发送SQL执行返回结果,也可以获取Mapper的接口
- SQL Mapper(映射器):由一个Java接口和注解组成,负责发送SQL去执行并且返回结果
(3)深入认识核心组件
(3.1)SqlSessionFactoryBuilder (构造器)
(3.2)SqlSessionFactory(工厂接口)
(1)干嘛的?
SqlSessionFactory是一个接口,在Mybatis中它存在两个实现类:SqlSessionManager和DefaultSqlSessionFactory。
每个基于 MyBatis 的应用都是以一个SqlSessionFactory的实例为中心的, 而SqlSessionFactory 唯一的作用就是生产 MyBatis 的核心接口对象 SqlSession,所以它的责任是唯一的。 我们往往会采用单例模式处理它。
(2)怎么干?
(1)第一步:构建Configuration
通过XMLConfigBuilder解析配置文件Mybatis-config.xml,读出所配置的参数,并且把读取的内容存入Configuration类对象中,包括:typeAliases别名、environments数据库环境、mappers映射器等等。Configuration用的是单例模式,几乎所有的MyBatis配置内容都会存放在这个单例对象中,方便后序把这些内容读出
(2)第二步:构建SqlSessionFactory
使用Configuration对象去创建SqlSessionFactory。SqlSessionFactory是一个接口而不是类,所以Mybatis提供了一个默认实现类DefaultSqlSessionFactory,这样就没有必要自己去创建新的SqlSessionFactory实现类了
<configuration>
<!--别名-->
<typeAliases>
<package name="com.itheima.interceptor"/>
</typeAliases>
<!--数据库环境-->
<environments default="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/test?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<!--映射文件,找到Dao的Xml配置文件,里面有具体的sql语句-->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
(3.3)SqlSession(会话)
是核心接口,有两个实现类,DefaultSqlSession(单线程)和SqlSessionManager(多线程)。其作用类似于JDBC中的Connection对象,代表着一个连接资源的启动。
作用有3:
- 获取Mapper接口
- 发送Sql给数据库
- 控制数据库事务
(3.4)SQLMapper映射器
最重要的组件,由一个接口和对应的Xml文件(或者注解)组成。映射器的主要作用就是将 SQL 查询到的结果映射为一个POJO,或者将POJO的数据插入到数据库中,并定义一些关于缓存等的重要内容。
(3.4.1)Xml实现映射器
(1)xml配置文件:SqlMapConfig.xml
<configuration>
<typeAliases>
<package name="com.itheima.interceptor"/>
</typeAliases>
<environments default="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/test?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
(2)映射器:IUserDao.xml配置具体sql语句
namespace表示映射到IUserDao接口
id表示映射到接口里的方法findAll
resultType表示执行结果映射到对象user里保存
<mapper namespace="com.itheima.dao.IUserDao">
<select id="findAll" resultType="user">
select * from user
</select>
</mapper>
(3)IUserDao接口
public interface IUserDao {
// 1-查询所有
List<User> findAll();
}
(3.4.2)注解实现映射器
使用注解就不需要单独写一个IUserDao.xml配置具体sql语句了,直接在接口中使用注解
(1)SqlMapConfig.xml配置环境(同上)
(2)IUserDao
public interface IUserDao {
// 1-查询所有
@Select("select * from user")
List<User> findAll();
}
(3.4.3)SqlSession发送SQL和Mapper接口发送SQL
(1)SqlSession发送SQL(不推荐)
有了映射器就可以通过SqlSession发送Sql了
(2)Mapper(Dao)接口发送SQL(推荐)
(3)区别: Mapper(Dao)接口发送SQL可以省去SqlSession里的功能性代码,提高可读性·
(3.5)生命周期
声明周期是组件的重要问题,错误使用会导致严重的多线程并发问题。
什么是生命周期?
生命周期就是每一个对象应该存活的时间,例如一个对象在没有引用的时候,就要关闭,然后被JVM销毁,释放内存资源。
- SQLSessionFactoryBuilder(构造器):创建SQLSessionFactory的方法执行完就消失,不会长期存在
- SQLSessionFactory(工厂接口):存在于整个Mybatis应用之中,一旦创建就要长期保存,直到不再使用Mybatis,相当于数据库的连接池
- SQLSession(会话):相当于数据库连接,存活在一个业务请求中,处理完一个请求就关闭连接,归还给SQLSessionFactory,使用try/catch/finally保证其关闭
- SQL Mapper(映射器):最大生命周期和SQLSession保持一致,一旦完成业务就废弃
(4)实例CRUD(注解形式)
(1)SqlMapConfig.xml配置环境(同上)
(2)IUserDao
public interface IUserDao {
// 1-查询所有
@Select("select * from user")
List<User> findAll();
// 2-插入对象
@Insert("insert into user(username,address,sex,birthday) value(#{username},#{address},#{sex},#{birthday})")
void saveUser(User user);
// 3-更新对象
@Update("update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}")
void updateUser(User user);
// 4-删除对象
@Delete("delete from user where id=#{userId}")
void deleteUser(Integer userId);
// 5-查询一个
@Select("select * from user where id=#{userId}")
User selectOne(Integer userId);
// 6-模糊查询
@Select("select * from user where username like #{name}")
List<User> selectLike(String userName);
// 7-查询总用户数
@Select("select count(id) from user")
int findTotal();
}
(4.1)测试类(Junit,可以看出各个组件的功能)
public class MybatisTest {
private InputStream inputStream;
private SqlSessionFactory sqlSessionFactory;
private SqlSession session;
private IUserDao userDao;
@Before
public void init() throws Exception{
// 1-读取配置文件(拿到资源)
inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
// 2-创建工厂(把资源给构建者)
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
// 3-使用工厂生产SQLSession对象
session=sqlSessionFactory.openSession(true);//true以后就不需要自己提交了
// 4-使用SQLSession创建Dao接口的代理对象(使用反射获取字节码class)
userDao=session.getMapper(IUserDao.class);
// 5-使用代理对象执行方法,结果放在List中,并且循环遍历
}
@After
public void destory() throws Exception{
// 6-释放资源
session.close();
inputStream.close();
}
// 查询所有数据(成功)
@Test
public void testFindAll(){
List<User> users=userDao.findAll();
for (User user: users) {
System.out.println(user);
}
}
}
(5)mybatis的解析和运行原理
(1)整体认识
Mybatis的运行过程分为两大步
- 第一步:读取配置文件Mybatis-config.xml缓存到Configuration对象,用来创建SqlSessionFactory
- 第二步:SqlSession的执行过程,需要掌握反射和动态代理技术
(2)构建SqlSessionFactory的过程
(1)第一步:构建Configuration
通过XMLConfigBuilder解析配置的xml文件,读出所配置的参数,并且把读取的内容存入Configuration类对象中。Configuration用的是单例模式,几乎所有的MyBatis配置内容都会存放在这个单例对象中,方便后序把这些内容读出
(2)第二步:构建SqlSessionFactory
使用Configuration对象去创建SqlSessionFactory。SqlSessionFactory是一个接口而不是类,所以Mybatis提供了一个默认实现类DefaultSqlSessionFactory,这样就没有必要自己去创建新的SqlSessionFactory实现类了
(2.1)构建Configuration
(1)Configuration作用如下
- 读入配置文件,包括基础配置的xml和映射器xml(注解)
- 初始化一些基础设置,比如Mybatis的别名、数据库环境、环境设置等等
- 提供单例,为后续创建SessionFactory提供配置参数
- 执行一些重要对象的初始化方法