第六篇 mybatis的運行原理(3):工廠方法模式,SqlSession的創建


一、工廠方法模式

            工廠模式是java中最常用的創建型設計模式之一,和之前提到的builder模式一樣,主要目的是為了代替new關鍵字創建對象的方式。工廠模式主要分三種,

       簡單工廠模式,工廠方法模式,抽象工廠模式。

      (1) 簡單工廠模式就是通過創建一個可以創建所有目標接口子類的工廠類,然后根據不同的需求,創建不同的目標類,雖然達到了工廠模式的目的,

               但是工廠類內部耦合嚴重,當需要增加新的目標子類創建方式時,就得去修改工廠類,擴展性差。

       (2)工廠方法模式是在簡單工廠模式的基礎上進行了進一步解耦,通過封裝,讓使用對象的不去關心對象的具體創建,只關注該類的功能,讓代碼

                更加整潔

       (3)抽象工廠模式是工廠方法模式的升級版本,他用來創建一組相關或者相互依賴的對象。他與工廠方法模式的區別就在於,工廠方法模式針對的是一

               個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構。在編程中,通常一個產品結構,表現為一個接口或者抽象類,也就是說,工廠方法

               模式提供的所有產品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的接口或抽象類,抽象工廠模式才是實際意義

               的工廠模式。

    由於接下來的內容只用了工廠方法模式,所以這里只舉該模式的例子。

package com.fan.seckill.factory;

/**
 * 生產工廠接口
 */
public interface ProducerFactory {
    public Food createFood(String foodType);
}
package com.fan.seckill.factory;

/**
 * 產品食物接口
 */
public interface Food {
    void getFoodType();
}
package com.fan.seckill.factory;

/**
 * 生產工廠默認實現類
 */
public class DefaultProducerFactory implements ProducerFactory{

    private Food food;
    @Override
    public Food createFood(String foodType) {
        if("rice".equals(foodType)) {
            food = new RiceFood();
        } else {
            food = new NoodleFood();
        }
        return this.food;
    }
}
package com.fan.seckill.factory;

/**
 * 食物默認實現類(面條)
 */
public class NoodleFood implements Food{
    @Override
    public void getFoodType() {
        System.out.println("面條!");
    }
}
package com.fan.seckill.factory;

/**
 * 食物默認實現類(米飯)
 */
public class RiceFood implements Food{
    @Override
    public void getFoodType() {
        System.out.println("米飯!");
    }
}
package com.fan.seckill.factory;

public class Test {
    public static void main(String[] args) {
        ProducerFactory producerFactory = new DefaultProducerFactory();
        Food food = producerFactory.createFood("noodle");
        food.getFoodType();
    }
}

從上面main方法的創建中就可以看出,食物的創建並沒有涉及到具體實現類的操作,都是由接口完成,封裝了具體的實現,只關注改接口的功能。

 

二、SqlSession的創建

     SqlSession接口是mybatis的核心接口之一,mybatis提供了兩個實現類,SqlSessionManager類和DefaultSqlSession類,創建過程中使用了工廠方法模式,開發人員常用

的DefaultSqlSession類,DefaultSqlSession對象的創建依賴於DefaultSqlSessionFactory類,下面是他們之間的關系依賴圖。

DefaultSqlSessionFactory類是一個具體工廠類,根據參數的不同需求,提供了多種創建sqlsession對象的方式,

最終歸為兩種創建方式,一種是根據數據源獲取數據庫連接創建sqlSession。另一種是通過已有的數據庫連接對象創建sqlSession。

SqlSessionFactory 接口提供的所有重載方式:

public interface SqlSessionFactory {
    SqlSession openSession();

    SqlSession openSession(boolean var1);

    SqlSession openSession(Connection var1);

    SqlSession openSession(TransactionIsolationLevel var1);

    SqlSession openSession(ExecutorType var1);

    SqlSession openSession(ExecutorType var1, boolean var2);

    SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);

    SqlSession openSession(ExecutorType var1, Connection var2);

    Configuration getConfiguration();
}

第一種創建方式:

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;

        DefaultSqlSession var8;
        try {
            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var12) {
            this.closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }

第二種創建方式:

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
        DefaultSqlSession var8;
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException var13) {
                autoCommit = true;
            }

            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            Transaction tx = transactionFactory.newTransaction(connection);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }

     為什么會有這兩種創建方式,主要還是因為構建connection的原因,我們知道ORM框架底層還是由JDBC實現,所以連接數據庫離不開connection對象,正常我們使用mybatis時都會

配置數據庫連接池這時候,connection的創建不再由mybatis維護,所以mybatis創建數據庫會話只需要使用現成的connection即可,所以在正常開發中,我們還是常用第二種方式。

      具體的創建一個sqlsession會話對象,除了之前學習過的配置對象configuration,還需要執行器對象executor,以及事務的默認提交屬性 autoCommit創建方法主要完成以下幾件事:

(1)獲取事務配置環境environment ,創建TransactionFactory對象(具體的該對象的獲取會在下篇博文提到)

(2)構建一個事務對象tx

(3)根據執行器類型構建執行器對象executor

(4)使用SqlSession的默認實現類DefaultSqlSession創建sqlsession對象


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM