如题, 现有系统为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
根据您提供的代码和配置信息,我注意到您将系统从使用JNDI+C3P0连接池替换为Druid连接池后,zeroDateTimeBehavior=convertToNull选项不再起作用。这个问题可能与初始化顺序有关。
在您的代码中,build()方法用于创建Druid数据源,并将其添加到dataSourceMap中。然后,在init()方法中,您通过调用init()方法来初始化所有的数据源。
可能存在的问题是,当您在build()方法中创建数据源时,zeroDateTimeBehavior选项还没有被正确设置。因此,在初始化数据源之前,这个选项可能会被默认值覆盖。
为了解决这个问题,您可以尝试修改代码,将zeroDateTimeBehavior选项的设置放在创建数据源之前。具体做法如下:
1. 在build()方法中,在创建DruidDataSource对象之前,获取zeroDateTimeBehavior的配置值。 2. 将获取到的zeroDateTimeBehavior的配置值设置给DruidDataSource对象。
这样,您就可以确保在创建数据源时正确地设置了zeroDateTimeBehavior选项。
另外,您还提到希望实现延迟初始化(Lazy init)的功能。为了实现这一点,您可以考虑将数据源的创建和初始化过程延迟到第一次真正需要连接数据库的时候进行,而不是在应用程序启动时就立即创建和初始化所有数据源。这需要对代码进行相应的修改和调整。
请注意,以上只是初步的排查和建议,具体解决方案还需根据您的实际情况进行进一步调试和修改。如果问题仍然存在,请提供更多错误日志和详细信息,以便我们能够给出更准确的帮助。
zeroDateTimeBehavior是一个MySQL JDBC驱动程序的配置选项,用于指定当从数据库中读取到0000-00-00 00:00:00这样的零日期值时,JDBC驱动程序应该如何处理。在旧的JDBC驱动程序版本中,这个选项的默认值是exception,表示抛出异常。但是,在一些特殊情况下,MySQL数据库中可能会包含零日期值,而且这些日期值在某些情况下可能是合法的,因此在一些情况下,应用程序需要能够正确地处理这些值,而不是抛出异常。
在Druid连接池中,您可以通过在JDBC URL中设置zeroDateTimeBehavior选项来控制这个行为。具体来说,如果您想将零日期值转换为Java的null值,可以将这个选项设置为convertToNull。如果您想将零日期值转换为一个合法的日期值,可以将这个选项设置为convertToNull。
初步排查可能是因为init和build顺序不一致导致的.但是也引入了init初始化慢的问题,连接url太多.我这边其实希望的是Lazy init
原回答者GitHub用户yansheng723
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。