001/*
002 *  Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core.mybatis;
017
018import com.mybatisflex.core.FlexConsts;
019import com.mybatisflex.core.FlexGlobalConfig;
020import com.mybatisflex.core.exception.FlexExceptions;
021import com.mybatisflex.core.row.RowMapper;
022import org.apache.ibatis.builder.xml.XMLConfigBuilder;
023import org.apache.ibatis.exceptions.ExceptionFactory;
024import org.apache.ibatis.executor.ErrorContext;
025import org.apache.ibatis.session.Configuration;
026import org.apache.ibatis.session.SqlSessionFactory;
027import org.apache.ibatis.session.SqlSessionFactoryBuilder;
028
029import java.io.IOException;
030import java.io.InputStream;
031import java.io.Reader;
032import java.util.Properties;
033
034public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
035
036    @Override
037    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
038        try {
039            // 需要 mybatis v3.5.13+
040            // https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
041            XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, reader, environment, properties);
042            return build(parser.parse());
043        } catch (Exception e) {
044            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
045        } finally {
046            ErrorContext.instance().reset();
047            try {
048                if (reader != null) {
049                    reader.close();
050                }
051            } catch (IOException e) {
052                // Intentionally ignore. Prefer previous error.
053            }
054        }
055    }
056
057
058    @Override
059    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
060        try {
061            // 需要 mybatis v3.5.13+
062            // https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
063            XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, inputStream, environment, properties);
064            return build(parser.parse());
065        } catch (Exception e) {
066            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
067        } finally {
068            ErrorContext.instance().reset();
069            try {
070                if (inputStream != null) {
071                    inputStream.close();
072                }
073            } catch (IOException e) {
074                // Intentionally ignore. Prefer previous error.
075            }
076        }
077    }
078
079
080    @Override
081    public SqlSessionFactory build(Configuration configuration) {
082        if (!FlexConfiguration.class.isAssignableFrom(configuration.getClass())) {
083            throw FlexExceptions.wrap("only support FlexMybatisConfiguration.");
084        }
085
086        SqlSessionFactory sessionFactory = super.build(configuration);
087
088        // 设置mybatis的默认mapper,
089        initDefaultMappers(configuration);
090
091        // 设置全局配置的 sessionFactory
092        initGlobalConfig(configuration, sessionFactory);
093
094        printBanner();
095
096        return sessionFactory;
097    }
098
099    /**
100     * 设置 mybatis-flex 默认的 Mapper
101     * 当前只有 RowMapper {@link RowMapper}
102     */
103    private void initDefaultMappers(Configuration configuration) {
104        configuration.addMapper(RowMapper.class);
105    }
106
107
108    private void printBanner() {
109        if (!FlexGlobalConfig.getDefaultConfig().isPrintBanner()) {
110            return;
111        }
112        String banner = "  __  __       _           _   _       _____ _           \n" +
113            " |  \\/  |_   _| |__   __ _| |_(_)___  |  ___| | _____  __\n" +
114            " | |\\/| | | | | '_ \\ / _` | __| / __| | |_  | |/ _ \\ \\/ /\n" +
115            " | |  | | |_| | |_) | (_| | |_| \\__ \\ |  _| | |  __/>  < \n" +
116            " |_|  |_|\\__, |_.__/ \\__,_|\\__|_|___/ |_|   |_|\\___/_/\\_\\\n" +
117            "         |___/ v" + FlexConsts.VERSION + " https://mybatis-flex.com";
118        System.out.println(banner);
119    }
120
121    /**
122     * 设置全局配置
123     *
124     * @param configuration
125     * @param sessionFactory
126     */
127    private void initGlobalConfig(Configuration configuration, SqlSessionFactory sessionFactory) {
128        String environmentId = configuration.getEnvironment().getId();
129
130        FlexGlobalConfig globalConfig = FlexGlobalConfig.getConfig(environmentId);
131        boolean configUnInitialize = globalConfig == null;
132        if (configUnInitialize) {
133            globalConfig = new FlexGlobalConfig();
134        }
135
136        globalConfig.setSqlSessionFactory(sessionFactory);
137        globalConfig.setConfiguration(configuration);
138
139        boolean isDefault = FlexGlobalConfig.getDefaultConfig() == globalConfig;
140        // #I9V9MB 多个SqlSessionFactory初始化时,被最后一个覆盖默认配置
141        FlexGlobalConfig.setConfig(environmentId, globalConfig, configUnInitialize || isDefault);
142    }
143
144
145}