1. 程式人生 > >SSM(二)MyBatis基本要素-核心類和介面

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)
    ; true關閉事務控制(預設),false開啟事務控制。
  • 作用域: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請求期間