db support remarks etc propertis

This commit is contained in:
Looly 2020-06-17 00:06:45 +08:00
parent 3b80f0a3d1
commit 9c434da9fb
16 changed files with 292 additions and 79 deletions

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
## 5.3.8 (2020-06-15)
## 5.3.8 (2020-06-16)
### 新特性
* 【core 】 增加ISO8601日期格式issue#904@Github
@ -12,6 +12,8 @@
* 【core 】 复制创建一个Bean对象, 并忽略某些属性(pr#130@Gitee)
* 【core 】 DateUtil.parse支持更多日期格式(issue#I1KHTB@Gitee)
* 【crypto 】 增加获取密钥空指针的检查(issue#925@Github)
* 【core 】 增加StrUtil.removeAny方法(issue#923@Github)
* 【db 】 增加部分Connection参数支持(issue#924@Github)
### Bug修复
* 【json 】 修复append方法导致的JSONConfig传递失效问题issue#906@Github

View File

@ -965,6 +965,25 @@ public class StrUtil {
return str.toString().replace(strToRemove, EMPTY);
}
/**
* 移除字符串中所有给定字符串当某个字符串出现多次则全部移除<br>
* removeAny("aa-bb-cc-dd", "a", "b") = --cc-dd
*
* @param str 字符串
* @param strsToRemove 被移除的字符串
* @return 移除后的字符串
* @since 5.3.8
*/
public static String removeAny(CharSequence str, CharSequence... strsToRemove) {
String result = str(str);
if (isNotEmpty(str)) {
for (CharSequence strToRemove : strsToRemove) {
result = removeAll(str, strToRemove);
}
}
return result;
}
/**
* 去除字符串中指定的多个字符如有多个则全部去除
*

View File

@ -1,10 +1,5 @@
package cn.hutool.db.ds;
import java.io.Closeable;
import java.io.Serializable;
import javax.sql.DataSource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.c3p0.C3p0DSFactory;
import cn.hutool.db.ds.dbcp.DbcpDSFactory;
@ -16,6 +11,10 @@ import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.setting.Setting;
import javax.sql.DataSource;
import java.io.Closeable;
import java.io.Serializable;
/**
* 抽象数据源工厂类<br>
* 通过实现{@link #getDataSource(String)} 方法实现数据源的获取<br>
@ -29,6 +28,9 @@ public abstract class DSFactory implements Closeable, Serializable{
private static final Log log = LogFactory.get();
/** 某些数据库需要的特殊配置项需要的配置项 */
public static final String[] KEY_CONN_PROPS = {"remarks", "useInformationSchema"};
/** 别名字段名URL */
public static final String[] KEY_ALIAS_URL = { "url", "jdbcUrl" };
/** 别名字段名:驱动名 */

View File

@ -1,14 +1,14 @@
package cn.hutool.db.ds.c3p0;
import java.beans.PropertyVetoException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import cn.hutool.setting.dialect.Props;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* Druid数据源工厂类
@ -48,8 +48,21 @@ public class C3p0DSFactory extends AbstractDSFactory {
}
ds.setUser(user);
ds.setPassword(pass);
poolSetting.toBean(ds);// 注入属性
// remarks等特殊配置since 5.3.8
final Props connProps = new Props();
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.getAndRemoveStr(key);
if(StrUtil.isNotBlank(connValue)){
connProps.setProperty(key, connValue);
}
}
ds.setProperties(connProps);
// 注入属性
poolSetting.toBean(ds);
return ds;
}
}

View File

@ -1,11 +1,11 @@
package cn.hutool.db.ds.dbcp;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import org.apache.commons.dbcp2.BasicDataSource;
import javax.sql.DataSource;
/**
* DBCP2数据源工厂类
@ -34,8 +34,19 @@ public class DbcpDSFactory extends AbstractDSFactory {
ds.setDriverClassName(driver);
ds.setUsername(user);
ds.setPassword(pass);
poolSetting.toBean(ds);// 注入属性
// remarks等特殊配置since 5.3.8
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.getAndRemoveStr(key);
if(StrUtil.isNotBlank(connValue)){
ds.addConnectionProperty(key, connValue);
}
}
// 注入属性
poolSetting.toBean(ds);
return ds;
}
}

View File

@ -1,15 +1,12 @@
package cn.hutool.db.ds.druid;
import java.util.Map.Entry;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import cn.hutool.setting.dialect.Props;
import com.alibaba.druid.pool.DruidDataSource;
import javax.sql.DataSource;
/**
* Druid数据源工厂类
@ -42,19 +39,24 @@ public class DruidDSFactory extends AbstractDSFactory {
protected DataSource createDataSource(String jdbcUrl, String driver, String user, String pass, Setting poolSetting) {
final DruidDataSource ds = new DruidDataSource();
// 基本信息
ds.setUrl(jdbcUrl);
ds.setDriverClassName(driver);
ds.setUsername(user);
ds.setPassword(pass);
// 规范化属性名
Properties druidProps = new Properties();
String keyStr;
for (Entry<String, String> entry : poolSetting.entrySet()) {
keyStr = StrUtil.addPrefixIfNot(entry.getKey(), "druid.");
druidProps.put(keyStr, entry.getValue());
// remarks等特殊配置since 5.3.8
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.getAndRemoveStr(key);
if(StrUtil.isNotBlank(connValue)){
ds.addConnectionProperty(key, connValue);
}
}
// 连接池信息
// Druid连接池配置信息规范化属性名
final Props druidProps = new Props();
poolSetting.forEach((key, value)-> druidProps.put(StrUtil.addPrefixIfNot(key, "druid."), value));
ds.configFromPropety(druidProps);
// 检查关联配置在用户未设置某项配置时

View File

@ -1,13 +1,14 @@
package cn.hutool.db.ds.hikari;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import cn.hutool.setting.dialect.Props;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
/**
* HikariCP数据源工厂类
@ -30,6 +31,16 @@ public class HikariDSFactory extends AbstractDSFactory {
@Override
protected DataSource createDataSource(String jdbcUrl, String driver, String user, String pass, Setting poolSetting) {
// remarks等特殊配置since 5.3.8
final Props connProps = new Props();
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.getAndRemoveStr(key);
if(StrUtil.isNotBlank(connValue)){
connProps.setProperty(key, connValue);
}
}
final Props config = new Props();
config.putAll(poolSetting);
@ -44,6 +55,9 @@ public class HikariDSFactory extends AbstractDSFactory {
config.put("password", pass);
}
return new HikariDataSource(new HikariConfig(config));
final HikariConfig hikariConfig = new HikariConfig(config);
hikariConfig.setDataSourceProperties(connProps);
return new HikariDataSource(hikariConfig);
}
}

View File

@ -3,32 +3,38 @@ package cn.hutool.db.ds.pooled;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.dialect.DriverUtil;
import java.util.Properties;
/**
* 数据库配置
* @author Looly
*
* @author Looly
*/
public class DbConfig {
//-------------------------------------------------------------------- Fields start
private String driver; //数据库驱动
private String url; //jdbc url
private String user; //用户名
private String pass; //密码
private int initialSize; //初始连接数
private int minIdle; //最小闲置连接数
private int maxActive; //最大活跃连接数
private long maxWait; //获取连接的超时等待
private String driver; //数据库驱动
private String url; //jdbc url
private String user; //用户名
private String pass; //密码
private int initialSize; //初始连接数
private int minIdle; //最小闲置连接数
private int maxActive; //最大活跃连接数
private long maxWait; //获取连接的超时等待
// 连接配置
private Properties connProps;
//-------------------------------------------------------------------- Fields end
//-------------------------------------------------------------------- Constructor start
public DbConfig() {
}
/**
* 构造
* @param url jdbc url
*
* @param url jdbc url
* @param user 用户名
* @param pass 密码
*/
@ -36,10 +42,11 @@ public class DbConfig {
init(url, user, pass);
}
//-------------------------------------------------------------------- Constructor end
/**
* 初始化
* @param url jdbc url
*
* @param url jdbc url
* @param user 用户名
* @param pass 密码
*/
@ -54,56 +61,85 @@ public class DbConfig {
throw new DbRuntimeException(e, "Get jdbc driver from [{}] error!", url);
}
}
//-------------------------------------------------------------------- Getters and Setters start
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public Properties getConnProps() {
return connProps;
}
public void setConnProps(Properties connProps) {
this.connProps = connProps;
}
public void addConnProps(String key, String value){
if(null == this.connProps){
this.connProps = new Properties();
}
this.connProps.setProperty(key, value);
}
//-------------------------------------------------------------------- Getters and Setters end
}

View File

@ -71,6 +71,15 @@ public class DbSetting {
dbConfig.setMaxActive(setting.getInt("maxActive", group, 8));
dbConfig.setMaxWait(setting.getLong("maxWait", group, 6000L));
// remarks等特殊配置since 5.3.8
String connValue;
for (String key : DSFactory.KEY_CONN_PROPS) {
connValue = config.get(key);
if(StrUtil.isNotBlank(connValue)){
dbConfig.addConnProps(key, connValue);
}
}
return dbConfig;
}
}

View File

@ -1,10 +1,13 @@
package cn.hutool.db.ds.pooled;
import cn.hutool.core.map.MapUtil;
import cn.hutool.db.DbUtil;
import cn.hutool.setting.dialect.Props;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* 池化
@ -15,11 +18,34 @@ public class PooledConnection extends ConnectionWraper{
private final PooledDataSource ds;
private boolean isClosed;
/**
* 构造
*
* @param ds 数据源
* @throws SQLException SQL异常
*/
public PooledConnection(PooledDataSource ds) throws SQLException {
this.ds = ds;
DbConfig config = ds.getConfig();
this.raw = DriverManager.getConnection(config.getUrl(), config.getUser(), config.getPass());
final DbConfig config = ds.getConfig();
final Props info = new Props();
final String user = config.getUser();
if (user != null) {
info.setProperty("user", user);
}
final String password = config.getPass();
if (password != null) {
info.setProperty("password", password);
}
// 其它参数
final Properties connProps = config.getConnProps();
if(MapUtil.isNotEmpty(connProps)){
info.putAll(connProps);
}
this.raw = DriverManager.getConnection(config.getUrl(), info);
}
public PooledConnection(PooledDataSource ds, Connection conn) {
@ -31,7 +57,7 @@ public class PooledConnection extends ConnectionWraper{
* 重写关闭连接实际操作是归还到连接池中
*/
@Override
public void close() throws SQLException {
public void close() {
this.ds.free(this);
this.isClosed = true;
}

View File

@ -1,10 +1,11 @@
package cn.hutool.db.ds.pooled;
import javax.sql.DataSource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import javax.sql.DataSource;
/**
* Hutool自身实现的池化数据源工厂类
*
@ -38,6 +39,15 @@ public class PooledDSFactory extends AbstractDSFactory {
dbConfig.setMaxActive(poolSetting.getInt("maxActive", 8));
dbConfig.setMaxWait(poolSetting.getLong("maxWait", 6000L));
// remarks等特殊配置since 5.3.8
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.get(key);
if(StrUtil.isNotBlank(connValue)){
dbConfig.addConnProps(key, connValue);
}
}
return new PooledDataSource(dbConfig);
}
}

View File

@ -1,10 +1,10 @@
package cn.hutool.db.ds.simple;
import javax.sql.DataSource;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import javax.sql.DataSource;
/**
* 简单数据源工厂类
*
@ -26,12 +26,13 @@ public class SimpleDSFactory extends AbstractDSFactory {
@Override
protected DataSource createDataSource(String jdbcUrl, String driver, String user, String pass, Setting poolSetting) {
return new SimpleDataSource(//
SimpleDataSource ds = new SimpleDataSource(//
jdbcUrl, //
user, //
pass, //
driver//
);
ds.setConnProps(poolSetting.getProps(Setting.DEFAULT_GROUP));
return ds;
}
}

View File

@ -1,16 +1,18 @@
package cn.hutool.db.ds.simple;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.dialect.DriverUtil;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.setting.Setting;
import cn.hutool.setting.dialect.Props;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/***
* 简易数据源没有使用连接池仅供测试或打开关闭连接非常少的场合使用
@ -28,6 +30,9 @@ public class SimpleDataSource extends AbstractDataSource {
private String url; // jdbc url
private String user; // 用户名
private String pass; // 密码
// 连接配置
private Properties connProps;
// -------------------------------------------------------------------- Fields end
/**
@ -87,6 +92,9 @@ public class SimpleDataSource extends AbstractDataSource {
config.getAndRemoveStr(DSFactory.KEY_ALIAS_PASSWORD), //
config.getAndRemoveStr(DSFactory.KEY_ALIAS_DRIVER)//
);
// 其它连接参数
this.connProps = config.getProps(Setting.DEFAULT_GROUP);
}
/**
@ -178,11 +186,40 @@ public class SimpleDataSource extends AbstractDataSource {
public void setPass(String pass) {
this.pass = pass;
}
public Properties getConnProps() {
return connProps;
}
public void setConnProps(Properties connProps) {
this.connProps = connProps;
}
public void addConnProps(String key, String value){
if(null == this.connProps){
this.connProps = new Properties();
}
this.connProps.setProperty(key, value);
}
// -------------------------------------------------------------------- Getters and Setters end
@Override
public Connection getConnection() throws SQLException {
return DriverManager.getConnection(this.url, this.user, this.pass);
final Props info = new Props();
if (this.user != null) {
info.setProperty("user", this.user);
}
if (this.pass != null) {
info.setProperty("password", this.pass);
}
// 其它参数
final Properties connProps = this.connProps;
if(MapUtil.isNotEmpty(connProps)){
info.putAll(connProps);
}
return DriverManager.getConnection(this.url, info);
}
@Override
@ -191,7 +228,7 @@ public class SimpleDataSource extends AbstractDataSource {
}
@Override
public void close() throws IOException {
public void close() {
// Not need to close;
}
}

View File

@ -1,10 +1,11 @@
package cn.hutool.db.ds.tomcat;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.AbstractDSFactory;
import cn.hutool.setting.Setting;
import cn.hutool.setting.dialect.Props;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
/**
* Tomcat-Jdbc-Pool数据源工厂类
@ -40,6 +41,20 @@ public class TomcatDSFactory extends AbstractDSFactory {
poolProps.setDriverClassName(driver);
poolProps.setUsername(user);
poolProps.setPassword(pass);
// remarks等特殊配置since 5.3.8
final Props connProps = new Props();
String connValue;
for (String key : KEY_CONN_PROPS) {
connValue = poolSetting.getAndRemoveStr(key);
if(StrUtil.isNotBlank(connValue)){
connProps.setProperty(key, connValue);
}
}
poolProps.setDbProperties(connProps);
// 连接池相关参数
poolSetting.toBean(poolProps);
return new DataSource(poolProps);
}

View File

@ -18,6 +18,13 @@ import java.util.List;
/**
* 数据库元数据信息工具类
*
* <p>
* 需要注意的是此工具类在某些数据库比如Oracle下无效此时需要手动在数据库配置中增加
* <pre>
* remarks = true
* useInformationSchema = true
* </pre>
*
* @author looly
*/
public class MetaUtil {

View File

@ -18,45 +18,54 @@ sqlLevel = debug
# 默认数据源
url = jdbc:sqlite:test.db
remarks = true
# 测试数据源
[test]
url = jdbc:sqlite:test.db
remarks = true
# 测试用HSQLDB数据库
[hsqldb]
url = jdbc:hsqldb:mem:mem_hutool
user = SA
pass =
remarks = true
# 测试用HSQLDB数据库
[h2]
url = jdbc:h2:mem:h2_hutool
user = sa
pass =
remarks = true
# 测试用HSQLDB数据库
[derby]
url = jdbc:derby:.derby/test_db;create=true
remarks = true
# 测试用Oracle数据库
[orcl]
url = jdbc:oracle:thin:@//looly.centos:1521/XE
user = looly
pass = 123456
remarks = true
[mysql]
url = jdbc:mysql://looly.centos8:3306/hutool_test?useSSL=false
user = root
pass = 123456
remarks = true
[postgre]
url = jdbc:postgresql://looly.centos:5432/test_hutool
user = postgres
pass = 123456
remarks = true
[sqlserver]
url = jdbc:sqlserver://looly.database.chinacloudapi.cn:1433;database=test;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.chinacloudapi.cn;loginTimeout=30;
user = looly@looly
pass = 123
pass = 123
remarks = true