org.foxbpm.engine.impl.mybatis.MyBatisSqlSessionFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.foxbpm.engine.impl.mybatis.MyBatisSqlSessionFactory.java

Source

/**
 * Copyright 1996-2014 FoxBPM ORG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @author ych
 */
package org.foxbpm.engine.impl.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import org.foxbpm.engine.exception.FoxBPMException;
import org.foxbpm.engine.impl.ProcessEngineConfigurationImpl;
import org.foxbpm.engine.impl.interceptor.Session;
import org.foxbpm.engine.impl.util.ExceptionUtil;
import org.foxbpm.engine.sqlsession.ISqlSession;
import org.foxbpm.engine.sqlsession.ISqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyBatisSqlSessionFactory implements ISqlSessionFactory {

    Logger log = LoggerFactory.getLogger(MyBatisSqlSessionFactory.class);
    private SqlSessionFactory sqlSessionFactory;

    protected static final Map<String, Map<String, String>> databaseSpecificStatements = new HashMap<String, Map<String, String>>();

    public static final Map<String, String> databaseSpecificLimitBeforeStatements = new HashMap<String, String>();
    public static final Map<String, String> databaseSpecificLimitAfterStatements = new HashMap<String, String>();
    public static final Map<String, String> databaseSpecificLimitBetweenStatements = new HashMap<String, String>();
    public static final Map<String, String> databaseSpecificOrderByStatements = new HashMap<String, String>();
    public static final Map<String, String> databaseOuterJoinLimitBetweenStatements = new HashMap<String, String>();
    public static final Map<String, String> databaseSpecificLimitBeforeNativeQueryStatements = new HashMap<String, String>();

    protected static Properties databaseTypeMappings = new Properties();

    static {

        String defaultOrderBy = " order by ${orderBy} ";
        //mysql specific
        databaseSpecificLimitBeforeStatements.put("mysql", "");
        databaseSpecificLimitAfterStatements.put("mysql", "LIMIT #{maxResults} OFFSET #{firstResult}");
        databaseSpecificLimitBetweenStatements.put("mysql", "");
        databaseOuterJoinLimitBetweenStatements.put("mysql", "");
        databaseSpecificOrderByStatements.put("mysql", defaultOrderBy);

        // oracle
        databaseSpecificLimitBeforeStatements.put("oracle", "select * from ( select a.*, ROWNUM rnum from (");
        databaseSpecificLimitAfterStatements.put("oracle",
                "  ) a where ROWNUM < #{lastRow}) where rnum  >= #{firstRow}");
        databaseSpecificLimitBetweenStatements.put("oracle", "");
        databaseOuterJoinLimitBetweenStatements.put("oracle", "");
        databaseSpecificOrderByStatements.put("oracle", defaultOrderBy);

        databaseSpecificLimitBeforeStatements.put("mssql", "SELECT SUB.* FROM (");
        databaseSpecificLimitAfterStatements.put("mssql",
                ")RES ) SUB WHERE SUB.rnk >= #{firstRow} AND SUB.rnk < #{lastRow}");
        databaseSpecificLimitBetweenStatements.put("mssql",
                ", row_number() over (ORDER BY #{orderBy}) rnk FROM ( select distinct RES.* ");
        databaseOuterJoinLimitBetweenStatements.put("mssql", "");
        databaseSpecificOrderByStatements.put("mssql", "");

        databaseTypeMappings.setProperty("MySQL", "mysql");
        databaseTypeMappings.setProperty("Oracle", "oracle");
        databaseTypeMappings.setProperty("Microsoft SQL Server", "mssql");
    }

    public void init(ProcessEngineConfigurationImpl processEngineConfig) throws SQLException {

        DataSource dataSource = processEngineConfig.getDataSource();
        if (dataSource == null) {
            throw ExceptionUtil.getException("00002003");
        }
        Connection connection = null;
        String databaseType = null;
        try {
            connection = dataSource.getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            String databaseProductName = databaseMetaData.getDatabaseProductName();
            log.debug("database product name: '{}'", databaseProductName);
            databaseType = databaseTypeMappings.getProperty(databaseProductName);
            if (databaseType == null) {
                throw new FoxBPMException(
                        "couldn't deduct database type from database product name '" + databaseProductName + "'");
            }

        } catch (SQLException e) {
            log.error("Exception while initializing Database connection", e);
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                log.error("Exception while closing the Database connection", e);
                throw e;
            }
        }
        if (sqlSessionFactory == null) {
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream("mybatis/mapping/mappings.xml");
                TransactionFactory transactionFactory = new ManagedTransactionFactory();
                Environment environment = new Environment("default", transactionFactory, dataSource);
                Reader reader = new InputStreamReader(inputStream);
                Properties properties = new Properties();
                if (databaseType != null) {
                    properties.put("limitBefore", databaseSpecificLimitBeforeStatements.get(databaseType));
                    properties.put("limitAfter", databaseSpecificLimitAfterStatements.get(databaseType));
                    properties.put("limitBetween", databaseSpecificLimitBetweenStatements.get(databaseType));
                    properties.put("limitOuterJoinBetween",
                            databaseOuterJoinLimitBetweenStatements.get(databaseType));
                    properties.put("orderBy", databaseSpecificOrderByStatements.get(databaseType));
                    properties.put("prefix", processEngineConfig.getPrefix());
                }
                XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties);
                Configuration configuration = parser.getConfiguration();
                configuration.setEnvironment(environment);
                configuration = parser.parse();

                Iterator<FoxbpmMapperConfig> mapperIterator = processEngineConfig.getCustomMapperConfig()
                        .iterator();
                while (mapperIterator.hasNext()) {
                    FoxbpmMapperConfig tmpMapper = mapperIterator.next();
                    log.debug("?mapperConifg{};", tmpMapper.getClass());
                    List<String> mapperPaths = tmpMapper.getMapperConfig();
                    if (mapperPaths != null) {
                        for (String mapPath : mapperPaths) {
                            InputStream input = Resources.getResourceAsStream(mapPath);
                            if (input != null) {
                                XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(input, configuration,
                                        mapPath, configuration.getSqlFragments());
                                xmlMapperBuilder.parse();
                                log.debug("?mapper{};", mapPath);
                            } else {
                                log.warn("mapper:" + mapPath + "?;");
                            }
                        }
                    }
                }
                sqlSessionFactory = new DefaultSqlSessionFactory(configuration);
            } catch (Exception e) {
                throw new RuntimeException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e);
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private SqlSession getSqlSession() {
        SqlSession sqlSession = null;
        if (sqlSessionFactory == null) {
            throw new FoxBPMException("mybatis sqlsession");
        }
        sqlSession = sqlSessionFactory.openSession();
        if (sqlSession == null) {
            throw new FoxBPMException("mybatis sqlSession");
        }
        return sqlSession;
    }

    public Class<?> getSessionType() {
        return ISqlSession.class;
    }

    public Session openSession() {
        return new MybatisSqlSession(getSqlSession());
    }

}