【MyBatis】使用說明:SqlSessionFactory+SqlSession

【問題描述】

單獨使用了MyBatis框架,沒有結合Spring框架,單獨在SQL server Manager中查詢數據的時候反應很快,但是在程序中查詢特別慢,總是卡在查詢的準備階段。數據庫那邊能看到創建了很多個連接沒有及時釋放掉。

【分析原因】

上網查詢了一些資料,一部分可能是查詢語句本身的查詢效率問題,一部分是MyBatis鏈接數據庫的時候SqlSessionFactory創建了多個鏈接或者SqlSession沒有及時關閉。

【解決方法】

1. 將創建SqlSessionFactory的方式改成單例模式,即只允許有且只有一個SqlSessionFactory實例存在。

2. SqlSession一旦創建需要及時關閉。

 

#-1->SqlSessionFactory的兩種創建方式

#-1.1->靜態模式創建SqlSessionFactory

單獨創建一個名爲【SessionFactory.java】文件。

放在static靜態塊中執行的代碼只會執行一次,保證只創建了一個SqlSessionFactory。

package com.demo.tools;

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 java.io.Reader;

public class DBtools {

    public static SqlSessionFactory sessionFactory;

    static {
        try{
            //配置文件地址
            String resources = "com/demo/confg/mybatisconfg.xml";
            //使用MyBatis提供的Resources類加載mybatis的配置文件
            Reader reader = Resources.getResourceAsReader(resources);
            //構建sqlSession的工廠
            sessionFactory = new SqlSessionFactoryBuilder().build(reader);

            System.out.println("靜態創建了一次SqlSessionFactory!");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //創建能執行映射文件中sql的sqlSession
    public static SqlSession getSession()
    {
        return sessionFactory.openSession();
    }
}

#-1.2->單例模式創建SqlSessionFactory

單獨創建一個名爲【SessionFactory.java】文件。

package com.slspt.tools;

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 java.io.Reader;

public class SessionFactory {

    private static SqlSessionFactory sqlSessionFactory;

    private static SqlSessionFactory getSqlSessionFactory(){
        //採用單例模式創建SqlSessionFactory
        if(sqlSessionFactory == null){
            try{
                //配置文件地址
                String resources = "com/slspt/confg/mybatisconfg.xml"; 
                //使用MyBatis提供的Resources類加載mybatis的配置文件
                Reader reader = Resources.getResourceAsReader(resources);
                //構建sqlSession的工廠
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                System.out.println("創建了一個sessionFactory!");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return sqlSessionFactory;
    }

    //創建能執行映射文件中sql的sqlSession
    public static SqlSession getSession()
    {
        return getSqlSessionFactory().openSession();
    }
}

 #-2->SqlSession創建以後必須關閉

創建一個Service類來管理數據操作,注意session.commit() session.rollback() session.close()分別放在try-catch-finally塊中

package com.services.Service;

import com.beans.DataBean;
import com.mappers.Mapper;

import com.tools.SessionFactory;
import org.apache.ibatis.session.SqlSession;

import java.util.ArrayList;

public class Service {

    private SqlSession session;
    private Mapper mapper;

    public Service() {
        super();
        session = SessionFactory.getSession();
        this.mapper = session.getMapper(Mapper.class);
        System.out.println("創建了一個session鏈接!^_^");
    }

    public ArrayList<DataBean> selectAllCity(String DateString){

        ArrayList<DataBean> listdata = new ArrayList<>();
        session = SessionFactory.getSession();
        try{
            listdata = mapper.selectAllCity(DateString);
            session.commit();
            System.out.println("session提交!");
        }catch (Exception e){
            e.printStackTrace();
            session.rollback();
        }finally {
            session.close();
            System.out.println("session關閉!");
        }

        return listdata;
    }

}

#-3->Bug記錄:

Cause:org.apache.ibatis.executor.ExcutorException: Executor was closed.

原因:使用了已經關閉的session!通過打印輸出可以看見session關閉的情況下,還在打印輸出session關閉。 

 出現這種情況的原因是service裏面一個session對應有多個Mapper:

構造函數中:

    this.session = SessionFactory.getSession();
    this.mapper = session.getMapper(YKSaleMapper.class);
    this.datemapper = session.getMapper(YKSaleDateMapper.class);

解決辦法:注意每個單獨的函數給session初始化一遍,添加如下代碼(如果單獨 一個session對一個Mapper文件,加不加無所謂)

session = SessionFactory.getSession(); 

  public ArrayList<String> getOperatorList(String Branch_no,String salechannel){
        ArrayList<String> operatorList = new ArrayList<String>();
        //每次給session初始化,避免出現bug【Executor was closed.】
        session = SessionFactory.getSession(); 
        //去數據庫取list
        try{
            operatorList = mapper.selectDistOperator(Branch_no,salechannel);
            session.commit();
            System.out.println("session提交!");
        }catch (Exception e){
            e.printStackTrace();
            session.rollback();
        }finally {
            session.close();
            System.out.println("session關閉!");
        }
        return operatorList;
    }

完整代碼如下:

package com.sys.dao;

import com.sys.beans.PremiumBean;
import com.sys.beans.YKSaleBean;
import com.sys.mapper.YKSaleDateMapper;
import com.sys.mapper.YKSaleMapper;
import com.sys.tools.SessionFactory;
import org.apache.ibatis.session.SqlSession;

import java.util.ArrayList;
import java.util.HashMap;

public class YKSaleCityDao {

    private SqlSession session;
    private YKSaleMapper mapper;
    private YKSaleDateMapper datemapper;

    //構造函數
    public YKSaleCityDao(){
        super();
        this.session = SessionFactory.getSession();
        this.mapper = session.getMapper(YKSaleMapper.class);
        this.datemapper = session.getMapper(YKSaleDateMapper.class);
    }

    private PremiumBean selectWithLike(String salechannel){

        PremiumBean data = new PremiumBean();
        //給session初始化避免出現使用已經關閉的session問題
        session = SessionFactory.getSession();
        try{

            data = mapper.selectWithLike(salechannel);
            session.commit();
            System.out.println("session提交!");
        }catch (Exception e){
            e.printStackTrace();
            session.rollback();
        }finally {
            session.close();
            System.out.println("session關閉!");
        }
        return data;
    }

    //返回需要展示的list數據
    public ArrayList<YKSaleBean> getUIList(String salechannel){

        ArrayList<YKSaleBean> listdata = new ArrayList<YKSaleBean>();

        for (int i = 0; i < insitutions.length; i++) {

            YKSaleBean bean = new YKSaleBean();

            //依次給Bean賦值

            //將bean添加到list中
            listdata.add(bean);
        }
        return listdata;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章