开发者社区> 问答> 正文

系统由JNDI+C3P0替换到Druid后zeroDateTimeBehavior=convertT

如题, 现有系统为JNDI+C3P0+Mysql-connector建立的连接池配置.后端架构为spring2+hibernate. 由于连接地址较多, 为了提高运维效率,所以对这块进行了改造. 但是这样用了以后zeroDateTimeBehavior=convertToNull失效 改造后配置如下: springContext-jdbc.xml

jdbc.properties

druid.initialSize=15 druid.minIdle=15 druid.maxIdle=100 druid.maxActive=100

druid.maxWait=60000 druid.timeBetweenEvictionRunsMillis=60000 druid.minEvictableIdleTimeMillis=300000

druid.validationQuery=SELECT 'x' #druid.validationQuery= druid.testWhileIdle=true druid.testOnBorrow=false druid.testOnReturn=false

druid.poolPreparedStatements=true druid.maxPoolPreparedStatementPerConnectionSize=20

druid.filters=stat,log4j

dataSource.cityCode=master010|slave010| dataSource.default.CityCode=master010

##master010 master010.jdbc.driverClass=com.mysql.jdbc.Driver master010.jdbc.jdbcUrl=jdbc:mysql://x.x.x.x:3306/beijing_xxgl?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull master010.jdbc.user=xxx master010.jdbc.password=xxx

封装的代码如下 @DaTa @slf4j public class XXXDruidDataSourceWrapper {

private Logger log = LoggerFactory.getLogger(XESDruidDataSourceWrapper.class);

/**
 * 管道分隔符
 */
private static final String PIPE ="|";

/**
 * Druid配置
 */
private int initialSize;
private int minIdle;
private int maxActive;
private long maxWait;
private long timeBetweenEvictionRunsMillis;
private long minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private String filters;

/**
 * 数据库配置后缀
 */
private String driverSuffix;
private String urlSuffix;
private String userSuffix;
private String passwordSuffix;

private List<DruidDataSource> dataSourceList = Lists.newArrayList();

/**
 * 配置文件的|风格连接池名称
 */
private String cityCodeArrayStr;

/**
 * 缺省CityCode连接池
 */
private String defaultCityCodeStr;

private DruidDataSource defaultDruidDataSource;

private XXXPropertyPlaceholderConfigurer configs;

public Map<String, Object> build() throws SQLException {
    Iterable<String> cityCodeArray = Splitter.on(PIPE)
            .omitEmptyStrings()
            .trimResults().split(cityCodeArrayStr);
    Map<String, Object> dataSourceMap = Maps.newHashMap();
        for (String cityCode : cityCodeArray) {
            DruidDataSource druidDataSource = new DruidDataSource();
            String driverClass = configs.getProperty(String.format(driverSuffix, cityCode));
            druidDataSource.setDriverClassName(driverClass);
            String jdbcUrl = configs.getProperty(String.format(urlSuffix, cityCode));
            druidDataSource.setUrl(jdbcUrl);
            String user = configs.getProperty(String.format(userSuffix, cityCode));
            druidDataSource.setUsername(user);
            String password = configs.getProperty(String.format(passwordSuffix, cityCode));
            druidDataSource.setPassword(password);

        /* 配置初始化大小、最小、最大 */
            druidDataSource.setInitialSize(initialSize);
            druidDataSource.setMinIdle(minIdle);
            druidDataSource.setMaxActive(maxActive);

        /*配置获取连接等待超时的时间*/
            druidDataSource.setMaxWait(maxWait);
        /*配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒*/
            druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

        /*配置一个连接在池中最小生存的时间,单位是毫秒*/
            druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

            druidDataSource.setValidationQuery(validationQuery);
            druidDataSource.setTestWhileIdle(testWhileIdle);
            druidDataSource.setTestOnBorrow(testOnBorrow);
            druidDataSource.setTestOnReturn(testOnReturn);

        /*
           打开PSCache,并且指定每个连接上PSCache的大小  如果用Oracle,
           则把poolPreparedStatements配置为true,mysql可以配置为false。
        */
            druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
            druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);

        /*配置监控统计拦截的filters*/
            druidDataSource.setFilters(filters);

            log.info("Create DateSource. The source name is {}" , cityCode);
            // 缺省连接池
            if (defaultCityCodeStr.equals(cityCode)) {
                this.defaultDruidDataSource = druidDataSource;
            }
            dataSourceMap.put(cityCode, druidDataSource);
            dataSourceList.add(druidDataSource);
        }
        log.info("The default datasource is {}", defaultCityCodeStr);
    return dataSourceMap;
}

public void init() throws SQLException {
    log.info("Initializing DateSource poll.");
    for (DruidDataSource druidDataSource : dataSourceList) {
        druidDataSource.init();
    }
    log.info("Initializing DateSource poll success.");
}

public void close() {
    log.info("Closing dateSource poll.");
    for (DruidDataSource druidDataSource : dataSourceList) {
        druidDataSource.close();
    }
    log.info("Closing DateSource success.");
}

}

原提问者GitHub用户yansheng723

展开
收起
山海行 2023-07-05 20:39:20 83 0
3 条回答
写回答
取消 提交回答
  • 根据您提供的代码和配置信息,我注意到您将系统从使用JNDI+C3P0连接池替换为Druid连接池后,zeroDateTimeBehavior=convertToNull选项不再起作用。这个问题可能与初始化顺序有关。

    在您的代码中,build()方法用于创建Druid数据源,并将其添加到dataSourceMap中。然后,在init()方法中,您通过调用init()方法来初始化所有的数据源。

    可能存在的问题是,当您在build()方法中创建数据源时,zeroDateTimeBehavior选项还没有被正确设置。因此,在初始化数据源之前,这个选项可能会被默认值覆盖。

    为了解决这个问题,您可以尝试修改代码,将zeroDateTimeBehavior选项的设置放在创建数据源之前。具体做法如下:

    1. 在build()方法中,在创建DruidDataSource对象之前,获取zeroDateTimeBehavior的配置值。 2. 将获取到的zeroDateTimeBehavior的配置值设置给DruidDataSource对象。

    这样,您就可以确保在创建数据源时正确地设置了zeroDateTimeBehavior选项。

    另外,您还提到希望实现延迟初始化(Lazy init)的功能。为了实现这一点,您可以考虑将数据源的创建和初始化过程延迟到第一次真正需要连接数据库的时候进行,而不是在应用程序启动时就立即创建和初始化所有数据源。这需要对代码进行相应的修改和调整。

    请注意,以上只是初步的排查和建议,具体解决方案还需根据您的实际情况进行进一步调试和修改。如果问题仍然存在,请提供更多错误日志和详细信息,以便我们能够给出更准确的帮助。

    2023-07-30 13:57:06
    赞同 展开评论 打赏
  • 北京阿里云ACE会长

    zeroDateTimeBehavior是一个MySQL JDBC驱动程序的配置选项,用于指定当从数据库中读取到0000-00-00 00:00:00这样的零日期值时,JDBC驱动程序应该如何处理。在旧的JDBC驱动程序版本中,这个选项的默认值是exception,表示抛出异常。但是,在一些特殊情况下,MySQL数据库中可能会包含零日期值,而且这些日期值在某些情况下可能是合法的,因此在一些情况下,应用程序需要能够正确地处理这些值,而不是抛出异常。

    在Druid连接池中,您可以通过在JDBC URL中设置zeroDateTimeBehavior选项来控制这个行为。具体来说,如果您想将零日期值转换为Java的null值,可以将这个选项设置为convertToNull。如果您想将零日期值转换为一个合法的日期值,可以将这个选项设置为convertToNull。

    2023-07-30 13:46:04
    赞同 展开评论 打赏
  • 初步排查可能是因为init和build顺序不一致导致的.但是也引入了init初始化慢的问题,连接url太多.我这边其实希望的是Lazy init

    原回答者GitHub用户yansheng723

    2023-07-06 11:52:35
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载