<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          最最常用的 SqlSessionFactory 和 SqlSession,你真的了解嗎?

          共 9516字,需瀏覽 20分鐘

           ·

          2022-06-08 23:04

          ????關(guān)注后回復(fù)?“進(jìn)群”?,拉你進(jìn)程序員交流群????

          前言

          學(xué)習(xí)框架一個(gè)比較好的路徑閱讀源碼。本文介紹的SqlSessionFactorySqlSession。可以通過(guò)了解SqlSessionFactory接口和SqlSession接口以及兩個(gè)的實(shí)現(xiàn)類入手,去看源碼了解實(shí)現(xiàn)過(guò)程。最好能把項(xiàng)目下載到本地,慢慢分析實(shí)現(xiàn)過(guò)程。

          MyBatis的持久化解決方案是將用戶從原始的JDBC訪問(wèn)中解放出來(lái),用戶只需要定義需要操作的SQL語(yǔ)句,無(wú)須關(guān)注底層的JDBC操作,就可以以面向?qū)ο蟮姆绞絹?lái)進(jìn)行持久化層操作。底層數(shù)據(jù)庫(kù)連接的獲取,數(shù)據(jù)訪問(wèn)的實(shí)現(xiàn),事務(wù)控制等都無(wú)須用戶關(guān)心,從而將應(yīng)用層從底層的JDBC/JTA API抽取出來(lái)。

          通過(guò)配置文件管理JDBC連接,讓MyBatis解決持久化的實(shí)現(xiàn)。在MyBatis中的常見(jiàn)對(duì)象有SqlSessionFactorySqlSession。本文這種介紹一下兩者的概念和使用。

          一、 SqlSessionFactory

          SqlSessionFactory是MyBatis的關(guān)鍵對(duì)象,它是個(gè)單個(gè)數(shù)據(jù)庫(kù)映射關(guān)系經(jīng)過(guò)編譯后的內(nèi)存鏡像。SqlSessionFactory對(duì)象的實(shí)例可以通過(guò)SqlSessionFactoryBuilder對(duì)象類獲得,而SqlSessionFactoryBuilder則可以從XML配置文件或一個(gè)預(yù)先定制的Configuration的實(shí)例構(gòu)建出SqlSessionFactory的實(shí)例。

          每一個(gè)MyBatis的應(yīng)用程序都以一個(gè)SqlSessionFactory對(duì)象的實(shí)例為核心。同時(shí)SqlSessionFactory也是線程安全的,SqlSessionFactory一旦被創(chuàng)建,應(yīng)該在應(yīng)用執(zhí)行期間都存在。在應(yīng)用運(yùn)行期間不要重復(fù)創(chuàng)建多次,建議使用單例模式。SqlSessionFactory是創(chuàng)建SqlSession的工廠。

          //SqlSessionFactory接口源碼如下所示:

          package?org.apache.ibatis.session;

          import?java.sql.Connection;

          public?interface?SqlSessionFactory?{

          ??SqlSession?openSession();//這個(gè)方法最經(jīng)常用,用來(lái)創(chuàng)建SqlSession對(duì)象.

          ??SqlSession?openSession(boolean?autoCommit);
          ??SqlSession?openSession(Connection?connection);
          ??SqlSession?openSession(TransactionIsolationLevel?level);

          ??SqlSession?openSession(ExecutorType?execType);
          ??SqlSession?openSession(ExecutorType?execType,?boolean?autoCommit);
          ??SqlSession?openSession(ExecutorType?execType,?TransactionIsolationLevel?level);
          ??SqlSession?openSession(ExecutorType?execType,?Connection?connection);

          ??Configuration?getConfiguration();

          }

          二、SqlSession

          SqlSession是MyBatis的關(guān)鍵對(duì)象,是執(zhí)行持久化操作的獨(dú)享,類似于JDBC中的Connection。它是應(yīng)用程序與持久層之間執(zhí)行交互操作的一個(gè)單線程對(duì)象,也是MyBatis執(zhí)行持久化操作的關(guān)鍵對(duì)象。SqlSession對(duì)象完全包含以數(shù)據(jù)庫(kù)為背景的所有執(zhí)行SQL操作的方法,它的底層封裝了JDBC連接,可以用SqlSession實(shí)例來(lái)直接執(zhí)行被映射的SQL語(yǔ)句。

          每個(gè)線程都應(yīng)該有它自己的SqlSession實(shí)例。SqlSession的實(shí)例不能被共享,同時(shí)SqlSession也是線程不安全的,絕對(duì)不能講SqlSeesion實(shí)例的引用放在一個(gè)類的靜態(tài)字段甚至是實(shí)例字段中。也絕不能將SqlSession實(shí)例的引用放在任何類型的管理范圍中,比如Servlet當(dāng)中的HttpSession對(duì)象中。使用完SqlSeesion之后關(guān)閉Session很重要,應(yīng)該確保使用finally塊來(lái)關(guān)閉它。

          //SqlSession接口源碼如下所示:

          package?org.apache.ibatis.session;

          import?java.io.Closeable;
          import?java.sql.Connection;
          import?java.util.List;
          import?java.util.Map;

          import?org.apache.ibatis.executor.BatchResult;

          public?interface?SqlSession?extends?Closeable?{

          ???T?selectOne(String?statement);

          ???T?selectOne(String?statement,?Object?parameter);

          ???List?selectList(String?statement);

          ???List?selectList(String?statement,?Object?parameter);

          ???List?selectList(String?statement,?Object?parameter,?RowBounds?rowBounds);

          ???Map?selectMap(String?statement,?String?mapKey);

          ???Map?selectMap(String?statement,?Object?parameter,?String?mapKey);

          ???Map?selectMap(String?statement,?Object?parameter,?String?mapKey,?RowBounds?rowBounds);

          ??void?select(String?statement,?Object?parameter,?ResultHandler?handler);

          ??void?select(String?statement,?ResultHandler?handler);

          ??void?select(String?statement,?Object?parameter,?RowBounds?rowBounds,?ResultHandler?handler);

          ??int?insert(String?statement);

          ??int?insert(String?statement,?Object?parameter);

          ??int?update(String?statement);

          ??int?update(String?statement,?Object?parameter);

          ??int?delete(String?statement);

          ??int?delete(String?statement,?Object?parameter);

          ??void?commit();

          ??void?commit(boolean?force);

          ??void?rollback();

          ??void?rollback(boolean?force);

          ??List?flushStatements();

          ??void?close();

          ??void?clearCache();

          ??Configuration?getConfiguration();

          ???T?getMapper(Class?type);

          ??Connection?getConnection();
          }

          三、SqlSessionFactory和SqlSession實(shí)現(xiàn)過(guò)程

          mybatis框架主要是圍繞著SqlSessionFactory進(jìn)行的,創(chuàng)建過(guò)程大概如下:

          (1)、定義一個(gè)Configuration對(duì)象,其中包含數(shù)據(jù)源、事務(wù)、mapper文件資源以及影響數(shù)據(jù)庫(kù)行為屬性設(shè)置settings

          (2)、通過(guò)配置對(duì)象,則可以創(chuàng)建一個(gè)SqlSessionFactoryBuilder對(duì)象

          (3)、通過(guò) SqlSessionFactoryBuilder 獲得SqlSessionFactory 的實(shí)例。

          (4)、SqlSessionFactory 的實(shí)例可以獲得操作數(shù)據(jù)的SqlSession實(shí)例,通過(guò)這個(gè)實(shí)例對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作

          并且如果想按照上述方式得到SqlSessionFactory,最好使用下面的mybatis-config。xml類似的配置。在這里mybatis-config.xml配置文件是沒(méi)有和Spring配置文件整合過(guò)得,如果項(xiàng)目中mybaits的配置文件和Spring配置文件整合過(guò)了,則下面的代碼運(yùn)行估計(jì)會(huì)出錯(cuò),因?yàn)橐话鉺pring和mybatis整合過(guò)之后,mybatis的配置文件基本沒(méi)有存在的必要了。

          之前在mybatis中配置的數(shù)據(jù)源和事務(wù)這兩個(gè)方面,一般的做法都會(huì)spring的配置文件,則下面的代碼加載mybatis-config.xml的時(shí)候,得不到必要的信息,創(chuàng)建的過(guò)程中會(huì)有問(wèn)題。所以在這里先給一份mybatis-config.xml單獨(dú)的配置文件。

          ??
          configuration?PUBLIC?"-//mybatis.org//DTD?Config?3.0//EN"??
          "http://mybatis.org/dtd/mybatis-3-config.dtd">??

          <configuration>???
          ??????
          ????<properties?resource="db.properties"/>??

          ??????
          ????<typeAliases>??
          ????????<typeAlias?type="cn.itcast.javaee.mybatis.app04.Student"?alias="student"/>??
          ????typeAliases>??

          ??????
          ????<environments?default="mysql_developer">??

          ??????????
          ????????<environment?id="mysql_developer">??
          ??????????????
          ????????????<transactionManager?type="jdbc"/>??
          ??????????????
          ????????????<dataSource?type="pooled">??
          ??????????????????
          ????????????????<property?name="driver"?value="${mysql.driver}"/>??
          ????????????????<property?name="url"?value="${mysql.url}"/>??
          ????????????????<property?name="username"?value="${mysql.username}"/>??
          ????????????????<property?name="password"?value="${mysql.password}"/>??
          ????????????dataSource>??
          ????????environment>??

          ??????????
          ????????<environment?id="oracle_developer">??
          ??????????????
          ????????????<transactionManager?type="jdbc"/>??
          ??????????????
          ????????????<dataSource?type="pooled">??
          ??????????????????
          ????????????????<property?name="driver"?value="${oracle.driver}"/>??
          ????????????????<property?name="url"?value="${oracle.url}"/>??
          ????????????????<property?name="username"?value="${oracle.username}"/>??
          ????????????????<property?name="password"?value="${oracle.password}"/>??
          ????????????dataSource>??
          ????????environment>??
          ????environments>??

          ??????
          ????<mappers>??
          ????????<mapper?resource="cn/itcast/javaee/mybatis/app14/StudentMapper.xml"/>??
          ????mappers>??

          configuration>??

          下面的這行代碼功能是通過(guò)配置文件mybatis-config.xml,創(chuàng)建SqlSessionFactory對(duì)象,然后產(chǎn)生SqlSession,執(zhí)行SQL語(yǔ)句。而mybatis的初始化發(fā)生在:

          SqlSessionFactory?sqlSessionFactory?=??new?SqlSessionFactoryBuilder().build(resourceAsStream);

          如果是spring和mybaits整合之后的配置文件,一般以這種方式實(shí)現(xiàn),SqlSessionFactory的創(chuàng)建:

          <bean?id="sqlSessionFactory"?class="org.mybatis.spring.SqlSessionFactoryBean">
          ????????<property?name="dataSource"?ref="dataSource">property>
          ????????
          ????????<property?name="mapperLocations"?value="classpath:com/cn/mapper/*.xml">property>
          bean>

          關(guān)于SqlSessionFactorySqlSession兩個(gè)對(duì)象給一個(gè)具體的使用過(guò)程:

          package?com.cn.testIUserService;

          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?com.cn.entity.User;

          public?class?MyBatisTest?{

          ????public?static?void?main(String[]?args)?{
          ????????try?{
          ????????????//讀取mybatis-config.xml文件
          ????????????InputStream?resourceAsStream?=?Resources.getResourceAsStream("mybatis-config.xml");
          ????????????//初始化mybatis,創(chuàng)建SqlSessionFactory類的實(shí)例
          ????????????SqlSessionFactory?sqlSessionFactory?=??new?SqlSessionFactoryBuilder().build(resourceAsStream);
          ????????????//創(chuàng)建session實(shí)例
          ????????????SqlSession?session?=?sqlSessionFactory.openSession();
          ????????????/*
          ?????????????*?接下來(lái)在這里做很多事情,到目前為止,目的已經(jīng)達(dá)到得到了SqlSession對(duì)象.通過(guò)調(diào)用SqlSession里面的方法,
          ?????????????*?可以測(cè)試MyBatis和Dao層接口方法之間的正確性,當(dāng)然也可以做別的很多事情,在這里就不列舉了
          ?????????????*/

          ????????????//插入數(shù)據(jù)
          ????????????User?user?=?new?User();
          ????????????user.setC_password("123");
          ????????????user.setC_username("123");
          ????????????user.setC_salt("123");
          ????????????//第一個(gè)參數(shù)為方法的完全限定名:位置信息+映射文件當(dāng)中的id
          ????????????session.insert("com.cn.dao.UserMapping.insertUserInformation",?user);
          ????????????//提交事務(wù)
          ????????????session.commit();
          ????????????//關(guān)閉session
          ????????????session.close();
          ????????}?catch?(IOException?e)?{
          ????????????e.printStackTrace();
          ????????}
          ????}
          }

          針對(duì)上面的代碼給出詳細(xì)的說(shuō)明關(guān)于SqlSessionFactorySqlSession創(chuàng)建過(guò)程涉及的內(nèi)容。

          結(jié)合上述SqlSessionFactorySqlSession使用過(guò)程和結(jié)構(gòu)圖,涉及到的方法為下面步驟,結(jié)合源碼中的方法為下面的步驟:

          • 第一步首先SqlSessionFactoryBuilder去讀取mybatis的配置文件,然后build一個(gè)DefaultSqlSessionFactory,即得到SqlSessionFactory
          //源碼中涉及的包和具體方法為:
          //涉及的包為:package?org.apache.ibatis.session;

          //第一個(gè)類為:SqlSessionFactoryBuilder,設(shè)計(jì)到此類的方法為下面部分:
          public?SqlSessionFactory?build(InputStream?inputStream)?{
          ????return?build(inputStream,?null,?null);
          ??}

          public?SqlSessionFactory?build(InputStream?inputStream,?String?environment,?Properties?properties)?{
          ????try?{
          ??????//通過(guò)XMLConfigBuilder解析配置文件,解析的配置相關(guān)信息都會(huì)封裝為一個(gè)Configuration對(duì)象
          ??????XMLConfigBuilder?parser?=?new?XMLConfigBuilder(inputStream,?environment,?properties);
          ??????//然后返回一個(gè)DefaultSqlSessionFactory
          ??????return?build(parser.parse());
          ????}?catch?(Exception?e)?{
          ??????throw?ExceptionFactory.wrapException("Error?building?SqlSession.",?e);
          ????}?finally?{
          ??????ErrorContext.instance().reset();
          ??????try?{
          ????????inputStream.close();
          ??????}?catch?(IOException?e)?{
          ????????//?Intentionally?ignore.?Prefer?previous?error.
          ??????}
          ????}
          ??}

          ?//得到DefaultSqlSessionFactory
          ?public?SqlSessionFactory?build(Configuration?config)?{
          ???return?new?DefaultSqlSessionFactory(config);
          ?}

          //第二個(gè)類為:DefaultSqlSessionFactory,涉及的方法為:
          ??public?DefaultSqlSessionFactory(Configuration?configuration)?{
          ????this.configuration?=?configuration;
          ??}

          第二步,獲取到SqlSessionFactory之后,就可以利用SqlSessionFactory方法的openSession來(lái)獲取SqlSession對(duì)象了。

          private?SqlSession?openSessionFromDataSource(ExecutorType?execType,?TransactionIsolationLevel?level,?boolean?autoCommit)?{
          ??Transaction?tx?=?null;
          ??try?{
          ????//通過(guò)Confuguration對(duì)象去獲取Mybatis相關(guān)配置信息,?Environment對(duì)象包含了數(shù)據(jù)源和事務(wù)的配置
          ????//?execType為執(zhí)行器類型,配置文件中定義
          ????// SimpleExecutor -- SIMPLE 就是普通的執(zhí)行器。
          ????//ReuseExecutor?-執(zhí)行器會(huì)重用預(yù)處理語(yǔ)句(prepared?statements)
          ????//BatchExecutor?--它是批量執(zhí)行器
          ????final?Environment?environment?=?configuration.getEnvironment();
          ????final?TransactionFactory?transactionFactory?=?getTransactionFactoryFromEnvironment(environment);
          ????tx?=?transactionFactory.newTransaction(environment.getDataSource(),?level,?autoCommit);
          ????//定義執(zhí)行器,是對(duì)statement的封裝
          ????final?Executor?executor?=?configuration.newExecutor(tx,?execType);
          ????//最后返回一個(gè)SqlSession
          ????return?new?DefaultSqlSession(configuration,?executor,?autoCommit);
          ??}?catch?(Exception?e)?{
          ????closeTransaction(tx);?//?may?have?fetched?a?connection?so?lets?call?close()
          ????throw?ExceptionFactory.wrapException("Error?opening?session.??Cause:?"?+?e,?e);
          ??}?finally?{
          ????ErrorContext.instance().reset();
          ??}
          }

          得到SqlSession對(duì)象之后就可以利用SqlSession內(nèi)部的方法進(jìn)行CRUD操作了。

          注意一點(diǎn),Connection對(duì)象是在SqlSession對(duì)象創(chuàng)建之后進(jìn)行CURD操作中創(chuàng)建的。深入查找之后找到在ManagedTransaction類中找到獲取Connection對(duì)象的關(guān)鍵代碼如下:

          ??protected?void?openConnection()?throws?SQLException?{
          ????if?(log.isDebugEnabled())?{
          ??????log.debug("Opening?JDBC?Connection");
          ????}
          ????//dataSource?來(lái)源有三種,JndiDatasource,PooledDataSource,UnpooledDataSource,配置文件中定義
          ????this.connection?=?this.dataSource.getConnection();
          ????if?(this.level?!=?null)?{
          ??????this.connection.setTransactionIsolation(this.level.getLevel());
          ????}
          ??}

          PooledDataSourceUnPooledDataSource的區(qū)別是PooledDataSource使用了連接池。為什么使用連接池呢?

          因?yàn)閯?chuàng)建一個(gè)Connection對(duì)象的過(guò)程,在底層就相當(dāng)于和數(shù)據(jù)庫(kù)建立的通信連接,在建立通信連接的過(guò)程,消耗了非常多的時(shí)間,而往往我們建立連接后(即創(chuàng)建Connection對(duì)象后),就執(zhí)行一個(gè)簡(jiǎn)單的SQL語(yǔ)句,然后就要拋棄掉,這是一個(gè)非常大的資源浪費(fèi)!

          mybatis針對(duì)這一個(gè)問(wèn)題提出的PooledDataSource使用了連接池。關(guān)于數(shù)據(jù)庫(kù)連接池的知識(shí)點(diǎn),可以自行百度,在這里就不擴(kuò)展介紹了。

          來(lái)源:blog.csdn.net/u013412772/article/

          details/73648537

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤(pán)了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久黄色片 | 亚洲无码五区 | 豆花视频操逼视频 | 亚洲无码第一区 | 久久人人爽人人爽人人片aV东京热 |