一、本课目标
- 了解MyBatis的三个基本要素
- 理解核心类和接口的作用域和声明周期(重点、难点)
- 掌握SQLSession的两种使用方式(重点)
二、MyBatis基本要素
MyBatis基本要素包括以下三个部分:
1、MyBatis的核心接口和类
- SqlSessionFactoryBuilder
- SqlSessionFactory
- SQLSession
2、mybatis-config.xml 系统核心配置文件
3、mapper.xml SQL映射文件
本节课只来学习第一个基本要素,即核心接口和类。
三、MyBatis的核心接口和类
核心接口和类包括以下三个部分:
1、SqlSessionFactroyBuilder
2、SqlSessionFactory
3、SqlSession
三者关系如下:
注:1、SqlSessionFactory是我们MyBatis整个应用程序的中心;整个程序都是以SqlSessionFactory的实例为核心的。
2、SqlSessionFactory对象是由SqlSessionFactoryBuilder对象创建而来的。
3、SqlSessionFactoryBuilder是通过xml配置文件或者configuration类的实例去构造这个对象。然后调用build()方法去构造SqlSessionFactory对象。
4、使用SqlSessionFactory对象的openSession()方法来获取SqlSession对象,有了SqlSession对象,我们就可以去进行数据库操作了,因为SqlSession里面包含了以数据库为背景所有执行sql操作的方法。
3.1SqlSessionFactoryBuilder
- 用过即丢,其生命周期只存在于方法体内
- 可重用其来创建多个SqlSessionFactory实例
-
负责构建SqlSessionFactory,并提供多个build方法的重载
在我们之前的测试中,使用的是读取xml文件,将其转换为输入流参数的形式提供给SqlSessionFactoryBuilder然后来构造SqlSessionFactory对象。
对于SqlSessionFactoryBuilder来说,创建完SqlSessionFactory对象之后,其使命也就完成了,可以直接丢弃了。
3.2SqlSessionFactory对象
注:
1、在使用openSession()方法创建一个SqlSession对象的时候传了一个布尔型的参数,
问题:获取SqlSessionFactory的代码是否可以进行优化?
可以使用静态代码块,以保证SqlSessionFactory只被创建一次。
创建一个工具类如下:
package cn.smbms.utils;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
private static SqlSessionFactory factory;
static{
String resource = "mybatis-config.xml";
try {
InputStream is = Resources.getResourceAsStream(resource);
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession createSqlSession() {
return factory.openSession(false);
}
public static void closeSqlSession(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.close();
}
}
}
工具类创建完成之后,就可以修改之前的测试代码了,如下:
package cn.smbms.dao.user;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import cn.smbms.utils.MyBatisUtil;
public class UserMapperTest {
private Logger logger = Logger.getLogger(UserMapperTest.class);
@Before
public void setUp() throws Exception {
}
@Test
public void test() {
int count = 0;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
// 4、调用mapper文件来对数据进行操作,操作之前必须将mapper文件引入到mabatis-config.xml中
count = sqlSession.selectOne("cn.smbms.dao.user.UserMapper.count");
logger.debug("UserMapperTest count ---->" + count);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
}
}
3.3SqlSession
- 包含了自行SQL所需的所有方法
- 对应一次数据库会话,会话结束必须关闭
- 线程级别,不能共享
1、在SqlSession里可以执行多次SQL语句,但一旦关闭了SqlSession就需要重新创建。
2、SqlSession示例不能被共享,也不是线程安全的。所以其最佳作用域是reqeust作用域内或者方法体内的作用域内。
1、SqlSession的获取方式:
2.SqlSession的两种使用方式
第一种方式:
在之前的测试中,如下代码:
count = sqlSession.selectOne("cn.smbms.dao.provider.providerCount");
就是直接运行映射的SQL语句。
第二种方式:
基于mapper接口方式来操作数据,也是MyBatis比较推崇的方式。
四、SqlSession的两种使用方式
需求说明:使用SqlSession的两种使用方式实现用户表的查询操作。
分析:
- 调用sqlSession.selectList()执行查询操作
- 调用sqlSession.getmapper(Mapper.class)执行DAO接口方法来实现对数据的查询操作
4.1调用sqlSession.selectList()执行查询操作
首先,在UserMapper.xml文件中增加新的select标签:
然后,增加新的单元测试的方法:
@Test
public void testGetuserList() {
List userList = null;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
// 4、调用mapper文件来对数据进行操作,操作之前必须将mapper文件引入到mabatis-config.xml中
userList = sqlSession.selectList("cn.smbms.dao.user.UserMapper.getUserList");
// userList = sqlSession.getMapper(UserMapper.class).getUserList();
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("testGetUserList userCode:" + user.getUserCode()
+ "and userName" + user.getUserName() + user.getModifyDate());
}
}
4.2调用sqlSession.getmapper(Mapper.class)执行DAO接口方法来实现对数据的查询操作
在增加完UserMapper.xml中的标签后,在cn.smbms.dao.user下重新建立一个接口文件:
package cn.smbms.dao.user;
import java.util.List;
import cn.smbms.pojo.User;
public interface UserMapper {
public List getUserList();
}
增加测试单元如下:
package cn.smbms.dao.user;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import cn.smbms.pojo.User;
import cn.smbms.utils.MyBatisUtil;
public class UserMapperTest {
private Logger logger = Logger.getLogger(UserMapperTest.class);
@Before
public void setUp() throws Exception {
}
@Test
public void test() {
int count = 0;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
// 4、调用mapper文件来对数据进行操作,操作之前必须将mapper文件引入到mabatis-config.xml中
count = sqlSession.selectOne("cn.smbms.dao.user.UserMapper.count");
logger.debug("UserMapperTest count ---->" + count);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
}
@Test
public void testGetuserList() {
List userList = null;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
// 4、调用mapper文件来对数据进行操作,操作之前必须将mapper文件引入到mabatis-config.xml中
// userList = sqlSession.selectList("cn.smbms.dao.user.UserMapper.getUserList");
userList = sqlSession.getMapper(UserMapper.class).getUserList();
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("testGetUserList userCode:" + user.getUserCode()
+ "and userName" + user.getUserName() + user.getModifyDate());
}
}
}
注:1、接口的方法的名字必须同xml文件中的id一致。