SSM(二)MyBatis基本要素-核心類和介面
一、目標
- 瞭解MyBatis的三個基本要素
- 理解核心類和介面的作用域和生命週期
- 掌握SqlSession的兩種使用方式
二、MyBatis基本要素
1. MyBatis的核心介面和類
- SqlSessionFactoryBuilder
- SqlSessionFactory
- SqlSession
2. mybatis-config.xml系統核心配置檔案,預設名稱為configuration.xml,檔案結構和子元素節點的含義進行系統學習。
3. mapper.xml SQL對映檔案
三、核心介面和類
SqlSessionFactory是整個MyBatis應用程式的中心,整個應用程式都是以SqlSessionFactory物件的例項為核心的。
首先建立得到SqlSessionFactory,如何建立得到SqlSessionFactory物件,需要SqlSessionFactoryBuilder,建立得到SqlSessionFactory物件。通過xml配置檔案或者configuration類的例項去構造然後獲取SqlSessionFactory物件。SqlSessionFactoryBuilder類的build()方法就可以獲得到SqlSessionFactory。
使用SqlSessionFactory是為了得到SqlSession例項。SqlSession是跟資料庫的一個會話,有了SqlSession,才能對資料庫進行增刪改查的操作。通過openSession()方法開啟一個會話,得到一個SqlSession物件例項,有了SqlSession就可以進行資料庫的操作,因為SqlSession物件包含了以資料庫為背景,所有執行SQL操作的方法。
四、核心物件-SqlSessionFactoryBuilder
- 用過即丟,其生命週期只存在於方法體內
- 可重用其來建立多個SqlSessionFactory例項
- 負責構建SqlSessionFactory,並提供多個build方法的過載
一旦得到SqlSessionFactory,SqlSessionFactoryBuilder就沒有用了,所以最佳的生命週期存在於方法體中。
五、核心物件-SqlSessionFactory
- SqlSessionFactory是每個MyBatis應用的核心
- 作用:建立SqlSession例項
- SqlSession session = sqlSessionFactory.openSession(boolean autoCommit)
- 作用域:Application
- 生命週期與應用的生命週期相同。
- 單例(程式執行期間有且僅有一個例項):存在於整個應用執行時,並且同時只存在一個物件例項。
六、獲取SqlSessionFactory的程式碼是否可以進行優化?
靜態程式碼塊,以保證SqlSessionFactory只被建立一次。
先去建立一個工具類MyBatisUtil,用於建立SqlSessionFactory物件。
新建cn.smbms.utils包,寫一個靜態程式碼塊
MyBatisUtil
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 String resource = "mybatis-config.xml";
private static SqlSessionFactory factory;
static {
try {
//首先獲得輸入流
InputStream is = Resources.getResourceAsStream(resource);
//得到SqlSessionFactory物件,通過SqlSessionFactoryBuilder的build方法
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static SqlSession createSqlSession() {
return factory.openSession(false);
}
public static void closeSqlSession(SqlSession sqlSession) {
if(null != sqlSession) {
sqlSession.close();
}
}
}
UserMapperTest
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.Test;
import cn.smbms.utils.MyBatisUtil;
public class UserMapperTest {
// 9.使用log4j列印日誌
private Logger logger = Logger.getLogger(UserMapperTest.class);
@Test
public void newTest() {
int count = 0;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
count = sqlSession.selectOne("cn.smbms.dao.user.UserMapper.count");
logger.debug("UserMapperTest ---> " + count);
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
}
}
最佳方案:使用依賴注入容器,Spring框架,進行繼承,進行SqlSessionFactory的管理。
七、核心物件-SqlSession
- 包含了執行SQL所需的所有方法(SqlSession用於持久化操作,類似於jdbc的connection)(通過sqlSession例項對資料庫增刪改查,直接執行已經對映的SQL語句)
- 對應一次資料庫會話,會話結束必須關閉
- 執行緒級別,不能共享
在do work中增刪改查,呼叫sqlSession提供的執行SQL的方法進行相應的操作,不管成敗,肯定要進入finally程式碼塊,對SqlSession進行關閉。
需要注意:SqlSession對應一次資料庫會話,會話不是永久的,會話結束要關閉,每次訪問資料庫時都要對SqlSession進行一次建立。
但是,在SqlSession裡可以執行多次SQL語句,但一旦關閉了SqlSession就需要重新建立。
各個執行緒,各個使用者之間的會話,不能共享,也不是執行緒安全的。最佳作用域的範圍在request作用域內,一次請求作用域內,或者一個方法體。
- SqlSession的獲取方式
- SqlSession的兩種使用方式:一、通過SqlSession例項直接執行對映的SQL語句。二、基於Mapper介面方式操作資料。
八、sqlSession的兩種使用方式
需求說明:使用sqlSession的兩種方式實現使用者表的查詢操作
分析:
呼叫sqlSession.selectList()執行查詢操作
呼叫sqlSession.getMapper(Mapper.class)執行DAO介面方法來實現對資料的查詢操作
實現:
第一種方式:
UserMapper.xml
<!-- 查詢使用者列表 -->
<select id="getUserList" resultType="cn.smbms.pojo.User">
select * from smbms_user
</select>
UserMapperTest
@Test
public void testGetUserList() {
List<User> userList = null;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.selectList("cn.smbms.dao.user.UserMapper.getUserList");
}finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for(User user : userList) {
logger.debug("testGetUserlist userCode: " + user.getUserCode() + " username: " + user.getUserName());
}
}
第二種:基於mapper介面的方式繼續操作資料
在cn.smbms.dao.user下創建於對映檔案同名的interface,UserMapper。提供介面方法,介面方法中的名字必須與SQL語句的id一一對應,getUserList()。介面又稱之為介面對映器。
package cn.smbms.dao.user;
import java.util.List;
import cn.smbms.pojo.User;
public interface UserMapper {
public List<User> getUserList();
}
在test方法中,userList=sqlSession.getMapper(UserMapper.class).getUserList()
@Test
public void testGetUserList2() {
List<User> userList = null;
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserList();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for(User user : userList) {
logger.debug("testGetUserlist userCode: " + user.getUserCode() + " username: " + user.getUserName());
}
}
九、小結
SqlSessionFactoryBuilder:用過即丟,推薦作用域在方法體內
SqlSessionFactory:最佳作用域範圍:應用的全域性作用域,生命週期與應用的宣告週期相同
SqlSession:作用域為執行緒級,生命週期為一個request請求期間