ren.hankai.cordwood.data.jpa.config.JpaDataSourceConfig.java Source code

Java tutorial

Introduction

Here is the source code for ren.hankai.cordwood.data.jpa.config.JpaDataSourceConfig.java

Source

/*******************************************************************************
 * Copyright (C) 2018 hankai
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/

package ren.hankai.cordwood.data.jpa.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallFilter;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.persistence.platform.database.HSQLPlatform;
import org.eclipse.persistence.platform.database.MySQLPlatform;
import org.eclipse.persistence.platform.database.OraclePlatform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import ren.hankai.cordwood.core.Preferences;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

/**
 * ???
 *
 * @author hankai
 * @version 1.0.0
 * @since Aug 18, 2016 2:19:51 PM
 */
public abstract class JpaDataSourceConfig {

    private static final Logger logger = LoggerFactory.getLogger(JpaDataSourceConfig.class);

    protected static String[] basePackages = null;

    /**
     * ???????????? ???
     *
     * @return ??
     * @author hankai
     * @since Jun 21, 2016 10:45:48 AM
     */
    private static Properties loadExternalConfig(String fileName) {
        Properties props = null;
        try {
            props = new Properties();
            props.load(new FileInputStream(Preferences.getDbConfigFile(fileName)));
        } catch (final IOException ex) {
            logger.warn("Failed to load external database configuration file for production profile.", ex);
        }
        if ((props != null) && (props.size() > 0)) {
            return props;
        }
        return null;
    }

    /**
     * ?
     *
     * @param props ????
     * @param dataSource Druid??
     * @author hankai
     * @since Dec 3, 2018 5:23:54 PM
     */
    private static void configureFilters(Properties props, DruidDataSource dataSource) {
        final List<Filter> filters = new ArrayList<>();
        // SQL
        final StatFilter statFilter = new StatFilter();
        String param = props.getProperty("pool.slow.sql.millis", "5000");
        statFilter.setSlowSqlMillis(Long.parseLong(param));
        param = props.getProperty("pool.log.slow.sql", "true");
        statFilter.setLogSlowSql(Boolean.parseBoolean(param));
        statFilter.setMergeSql(true); // ??sql
        filters.add(statFilter); // ?
        // SLF4J
        final Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
        slf4jLogFilter.setResultSetLogEnabled(false);
        filters.add(slf4jLogFilter);
        // SQL
        param = props.getProperty("pool.check.sql.injection", "false");
        if (Boolean.parseBoolean(param)) {
            // Druid wall filter ? https://github.com/alibaba/druid/wiki/?-wallfilter
            final WallFilter wallFilter = new WallFilter();
            // wallFilter.getConfig().setXX
            wallFilter.setLogViolation(true);// SQL?
            filters.add(wallFilter);
        }
        dataSource.setProxyFilters(filters);
    }

    /**
     * ????
     *
     * @param props ???e.g. mysql.properties
     * @param dataSource Druid ??
     * @author hankai
     * @since Jul 31, 2018 3:21:48 PM
     */
    private static void configureDataSourcePool(Properties props, DruidDataSource dataSource) {
        //  url?user?password
        dataSource.setDriverClassName(props.getProperty("driverClassName"));
        dataSource.setUrl(props.getProperty("url"));
        dataSource.setUsername(props.getProperty("username"));
        dataSource.setPassword(props.getProperty("password"));

        // ??????
        String param = props.getProperty("pool.initial.size", "1");
        dataSource.setInitialSize(Integer.parseInt(param));
        param = props.getProperty("pool.min.idle", "1");
        dataSource.setMinIdle(Integer.parseInt(param));
        param = props.getProperty("pool.max.active", "20");
        dataSource.setMaxActive(Integer.parseInt(param));

        // ??
        param = props.getProperty("pool.max.wait", "60000");
        dataSource.setMaxWait(Long.parseLong(param));

        // ?????
        param = props.getProperty("pool.time.between.eviction.runs.millis", "60000");
        dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(param));

        // ????
        param = props.getProperty("pool.min.evictable.idle.time.millis", "300000");
        dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(param));

        dataSource.setTestWhileIdle(true);// ??
        dataSource.setTestOnBorrow(false);// ???
        dataSource.setTestOnReturn(false);// ??

        // PSCache?PSCache?
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

        param = props.getProperty("pool.debug", "false");
        if (Boolean.parseBoolean(param)) {
            // ??
            dataSource.setRemoveAbandoned(true);
            // ??
            param = props.getProperty("pool.remove.abandoned.timeout", "180");
            dataSource.setRemoveAbandonedTimeout(Integer.parseInt(param));
            dataSource.setLogAbandoned(true);
        } else {
            dataSource.setRemoveAbandoned(false);
        }
        // ?
        configureFilters(props, dataSource);
    }

    /**
     * ??
     */
    public JpaDataSourceConfig() {
        String pkg = this.getClass().getPackage().getName();
        if (StringUtils.isNotEmpty(pkg) && (basePackages == null)) {
            pkg = pkg.split("\\.")[0];
            basePackages = new String[] { pkg };
        }
    }

    /**
     * HSQL ???
     *
     * @author hankai
     * @version 1.0.0
     * @since Jul 31, 2018 2:59:52 PM
     */
    @Profile(Preferences.PROFILE_HSQL)
    @Configuration
    public static class HsqlConfig {

        /**
         * ??
         *
         * @return ??
         * @author hankai
         * @since Oct 25, 2016 11:35:04 AM
         */
        @Bean
        public DataSource dataSource() {
            final Properties props = loadExternalConfig("hsql.properties");
            // ??????
            String url = props.getProperty("url");
            if (url.contains("%s")) {
                // ????
                final String dbPath = Preferences.getDbDir() + File.separator + "application";
                url = String.format(props.getProperty("url"), dbPath);
                props.setProperty("url", url);
            }

            final DruidDataSource dataSource = new DruidDataSource();
            configureDataSourcePool(props, dataSource);
            // ??sql?
            dataSource.setValidationQuery("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS");
            return dataSource;
        }

        /**
         * ????
         *
         * @return ????
         * @author hankai
         * @since Oct 25, 2016 11:35:17 AM
         */
        @Bean
        public JpaDataSourceInfo dataSourceInfo() {
            return new JpaDataSourceInfo(HSQLPlatform.class.getName(), basePackages);
        }
    }

    /**
     * MySQL ???
     *
     * @author hankai
     * @version 1.0.0
     * @since Jul 31, 2018 3:00:14 PM
     */
    @Configuration
    @Profile(Preferences.PROFILE_MYSQL)
    public static class MySqlConfig {

        /**
         * MySQL ??
         *
         * @return ??
         * @author hankai
         * @since Oct 25, 2016 11:35:34 AM
         */
        @Bean
        public DataSource dataSource() {
            final Properties props = loadExternalConfig("mysql.properties");
            final DruidDataSource dataSource = new DruidDataSource();
            configureDataSourcePool(props, dataSource);
            dataSource.setValidationQuery("select 1");// ??sql?
            return dataSource;
        }

        @Bean
        public JpaDataSourceInfo dataSourceInfo() {
            return new JpaDataSourceInfo(MySQLPlatform.class.getName(), basePackages);
        }
    }

    /**
     * Oracle ???
     *
     * @author hankai
     * @version 1.0.0
     * @since Jul 31, 2018 3:00:41 PM
     */
    @Configuration
    @Profile(Preferences.PROFILE_ORACLE)
    public static class OracleConfig {

        /**
         * ORACLE ??
         *
         * @return ??
         * @author hankai
         * @since Oct 25, 2016 11:35:50 AM
         */
        @Bean
        public DataSource dataSource() {
            final Properties props = loadExternalConfig("oracle.properties");
            final DruidDataSource dataSource = new DruidDataSource();
            configureDataSourcePool(props, dataSource);
            dataSource.setValidationQuery("select * from dual");// ??sql?
            return dataSource;
        }

        @Bean
        public JpaDataSourceInfo dataSourceInfo() {
            return new JpaDataSourceInfo(OraclePlatform.class.getName(), basePackages);
        }
    }
}