This commit is contained in:
Looly 2024-01-19 10:06:49 +08:00
parent 430c63b9bc
commit b405b2526d
30 changed files with 444 additions and 312 deletions

View File

@ -13,10 +13,12 @@
package org.dromara.hutool.db;
import org.dromara.hutool.core.func.SerConsumer;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.dialect.Dialect;
import org.dromara.hutool.db.dialect.DialectFactory;
import org.dromara.hutool.db.ds.DSUtil;
import org.dromara.hutool.db.ds.DSWrapper;
import org.dromara.hutool.db.transaction.TransactionLevel;
import org.dromara.hutool.log.LogUtil;
@ -67,6 +69,18 @@ public class Db extends AbstractDb<Db> {
return of(ds, DialectFactory.getDialect(ds));
}
/**
* 创建Db
*
* @param config 数据库配置
* @return Db
*/
public static Db of(final DbConfig config){
final DSWrapper ds = DSUtil.createDS(config);
final Dialect dialect = ObjUtil.defaultIfNull(config.getDialect(), DialectFactory.newDialect(ds));
return of(ds, dialect);
}
/**
* 创建Db
*

View File

@ -23,10 +23,7 @@ import org.dromara.hutool.db.dialect.Dialect;
import org.dromara.hutool.db.handler.NumberHandler;
import org.dromara.hutool.db.handler.PageResultHandler;
import org.dromara.hutool.db.handler.RsHandler;
import org.dromara.hutool.db.sql.Query;
import org.dromara.hutool.db.sql.QuoteWrapper;
import org.dromara.hutool.db.sql.SqlBuilder;
import org.dromara.hutool.db.sql.SqlUtil;
import org.dromara.hutool.db.sql.*;
import java.io.Serializable;
import java.sql.Connection;
@ -79,7 +76,7 @@ public class DialectRunner implements Serializable {
try {
if (1 == records.length) {
//单条单独处理
ps = dialect.psForInsert(conn, records[0]);
ps = dialect.psForInsert(false, conn, records[0]);
return new int[]{ps.executeUpdate()};
}
@ -163,7 +160,7 @@ public class DialectRunner implements Serializable {
PreparedStatement ps = null;
try {
ps = dialect.psForInsert(conn, record);
ps = dialect.psForInsert(true, conn, record);
ps.executeUpdate();
if (null == generatedKeysHandler) {
return null;

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.db.config;
import java.util.Properties;
/**
* 数据库连接配置提供包括jdbcUrl用户名和密码等信息
*
* @param <T> 返回值类型用于继承后链式调用
*/
@SuppressWarnings("unchecked")
public class ConnectionConfig<T extends ConnectionConfig<?>> {
private String driver; //数据库驱动
private String url; //jdbc url
private String user; //用户名
private String pass; //密码
/**
* 连接配置
*/
private Properties connProps;
/**
* 连接池配置
*/
private Properties poolProps;
/**
* 获取JDBC驱动
*
* @return JDBC驱动
*/
public String getDriver() {
return driver;
}
/**
* 设置JDBC驱动
*
* @param driver JDBC驱动
* @return this
*/
public T setDriver(final String driver) {
this.driver = driver;
return (T) this;
}
/**
* 获取JDBC URL
*
* @return JDBC URL
*/
public String getUrl() {
return url;
}
/**
* 设置JDBC URL
*
* @param url JDBC URL
* @return this
*/
public T setUrl(final String url) {
this.url = url;
return (T) this;
}
/**
* 获取用户名
*
* @return 用户名
*/
public String getUser() {
return user;
}
/**
* 设置用户名
*
* @param user 用户名
* @return this
*/
public T setUser(final String user) {
this.user = user;
return (T) this;
}
/**
* 获取密码
*
* @return 密码
*/
public String getPass() {
return pass;
}
/**
* 设置密码
*
* @param pass 密码
* @return this
*/
public T setPass(final String pass) {
this.pass = pass;
return (T) this;
}
/**
* 获取连接属性
*
* @return 连接属性
*/
public Properties getConnProps() {
return connProps;
}
/**
* 设置连接属性
*
* @param connProps 连接属性
* @return this
*/
public T setConnProps(final Properties connProps) {
this.connProps = connProps;
return (T) this;
}
/**
* 增加连接属性
*
* @param key 属性名
* @param value 属性值
* @return this
*/
public T addConnProps(final String key, final String value) {
if (null == this.connProps) {
this.connProps = new Properties();
}
this.connProps.setProperty(key, value);
return (T) this;
}
/**
* 获取连接池属性
*
* @return 连接池属性
*/
public Properties getPoolProps() {
return poolProps;
}
/**
* 设置连接池属性
*
* @param poolProps 连接池属性
* @return this
*/
public T setPoolProps(final Properties poolProps) {
this.poolProps = poolProps;
return (T) this;
}
/**
* 增加连接池属性
*
* @param key 属性名
* @param value 属性值
* @return this
*/
public T addPoolProps(final String key, final String value) {
if (null == this.poolProps) {
this.poolProps = new Properties();
}
this.poolProps.setProperty(key, value);
return (T) this;
}
}

View File

@ -40,10 +40,6 @@ public interface DSKeys {
* 配置文件中配置属性名是否忽略大小写
*/
String KEY_CASE_INSENSITIVE = "caseInsensitive";
/**
* 配置文件中配置属性名INSERT是否返回主键
*/
String KEY_RETURN_GENERATED_KEY = "returnGeneratedKey";
/**
* 某些数据库需要的特殊配置项需要的配置项

View File

@ -12,13 +12,12 @@
package org.dromara.hutool.db.config;
import org.dromara.hutool.db.Db;
import org.dromara.hutool.db.dialect.Dialect;
import org.dromara.hutool.db.driver.DriverUtil;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.sql.filter.SqlFilter;
import org.dromara.hutool.db.sql.filter.SqlFilterChain;
import java.util.Properties;
/**
* 数据库配置包括
* <ul>
@ -30,9 +29,10 @@ import java.util.Properties;
*
* @author Looly
*/
public class DbConfig {
public class DbConfig extends ConnectionConfig<DbConfig> {
// region ----- of
/**
* 创建DsConfig
*
@ -55,189 +55,33 @@ public class DbConfig {
}
// endregion
private String driver; //数据库驱动
private String url; //jdbc url
private String user; //用户名
private String pass; //密码
// 连接配置
private Properties connProps;
// 连接池配置
private Properties poolProps;
// 其它配置
/**
* 是否大小写不敏感默认大小写不敏感
*/
private boolean caseInsensitive = true;
/**
* 是否INSERT语句中默认返回主键默认返回主键
*/
private boolean returnGeneratedKey = true;
/**
* SQL过滤器用于在生成SQL前对SQL做操作如记录日志等
*/
private SqlFilterChain sqlFilters;
/**
* 自定义{@link DSFactory}用于自定义连接池
*/
private DSFactory dsFactory;
/**
* 自定义数据库方言
*/
private Dialect dialect;
/**
* 构造
*/
public DbConfig() {
}
/**
* 获取JDBC驱动
*
* @return JDBC驱动
*/
public String getDriver() {
return driver;
}
/**
* 设置JDBC驱动
*
* @param driver JDBC驱动
* @return this
*/
public DbConfig setDriver(final String driver) {
this.driver = driver;
return this;
}
/**
* 获取JDBC URL
*
* @return JDBC URL
*/
public String getUrl() {
return url;
}
/**
* 设置JDBC URL
*
* @param url JDBC URL
* @return this
*/
public DbConfig setUrl(final String url) {
this.url = url;
return this;
}
/**
* 获取用户名
*
* @return 用户名
*/
public String getUser() {
return user;
}
/**
* 设置用户名
*
* @param user 用户名
* @return this
*/
public DbConfig setUser(final String user) {
this.user = user;
return this;
}
/**
* 获取密码
*
* @return 密码
*/
public String getPass() {
return pass;
}
/**
* 设置密码
*
* @param pass 密码
* @return this
*/
public DbConfig setPass(final String pass) {
this.pass = pass;
return this;
}
/**
* 获取连接属性
*
* @return 连接属性
*/
public Properties getConnProps() {
return connProps;
}
/**
* 设置连接属性
*
* @param connProps 连接属性
* @return this
*/
public DbConfig setConnProps(final Properties connProps) {
this.connProps = connProps;
return this;
}
/**
* 增加连接属性
*
* @param key 属性名
* @param value 属性值
* @return this
*/
public DbConfig addConnProps(final String key, final String value) {
if (null == this.connProps) {
this.connProps = new Properties();
}
this.connProps.setProperty(key, value);
return this;
}
/**
* 获取连接池属性
*
* @return 连接池属性
*/
public Properties getPoolProps() {
return poolProps;
}
/**
* 设置连接池属性
*
* @param poolProps 连接池属性
* @return this
*/
public DbConfig setPoolProps(final Properties poolProps) {
this.poolProps = poolProps;
return this;
}
/**
* 增加连接池属性
*
* @param key 属性名
* @param value 属性值
* @return this
*/
public DbConfig addPoolProps(final String key, final String value) {
if (null == this.poolProps) {
this.poolProps = new Properties();
}
this.poolProps.setProperty(key, value);
return this;
}
/**
* 获取是否在结果中忽略大小写
*
@ -259,34 +103,12 @@ public class DbConfig {
return this;
}
/**
* INSERT语句中是否返回主键
*
* @return 是否返回主键
*/
public boolean isReturnGeneratedKey() {
return this.returnGeneratedKey;
}
/**
* 设置是否INSERT语句中默认返回主键默认返回主键<br>
* 如果false则在Insert操作后返回影响行数
* 主要用于某些数据库不支持返回主键的情况
*
* @param isReturnGeneratedKey 是否INSERT语句中默认返回主键
* @return this
*/
public DbConfig setReturnGeneratedKey(final boolean isReturnGeneratedKey) {
returnGeneratedKey = isReturnGeneratedKey;
return this;
}
/**
* 获取SQL过滤器
*
* @return SQL过滤器
*/
public SqlFilterChain getSqlFilters(){
public SqlFilterChain getSqlFilters() {
return this.sqlFilters;
}
@ -296,11 +118,51 @@ public class DbConfig {
* @param filter SQL过滤器
* @return this
*/
public DbConfig addSqlFilter(final SqlFilter filter){
if(null == this.sqlFilters){
public DbConfig addSqlFilter(final SqlFilter filter) {
if (null == this.sqlFilters) {
this.sqlFilters = new SqlFilterChain();
}
this.sqlFilters.addChain(filter);
return this;
}
/**
* 获取自定义数据源工厂
*
* @return 数据源工厂
*/
public DSFactory getDsFactory() {
return dsFactory;
}
/**
* 设置数据源工厂
*
* @param dsFactory 数据源工厂
* @return this
*/
public DbConfig setDsFactory(final DSFactory dsFactory) {
this.dsFactory = dsFactory;
return this;
}
/**
* 获取自定义方言
*
* @return 自定义方言
*/
public Dialect getDialect() {
return dialect;
}
/**
* 设置自定义方言
*
* @param dialect 自定义方言
* @return this
*/
public DbConfig setDialect(final Dialect dialect) {
this.dialect = dialect;
return this;
}
}

View File

@ -114,8 +114,6 @@ public class SettingConfigParser implements ConfigParser {
throw new DbException("No JDBC URL!");
}
final SqlLogFilter sqlLogFilter = getSqlLogFilter(setting);
// 自动识别Driver
String driver = setting.getAndRemove(DSKeys.KEY_ALIAS_DRIVER);
if (StrUtil.isBlank(driver)) {
@ -126,18 +124,19 @@ public class SettingConfigParser implements ConfigParser {
.setUrl(url)
.setDriver(driver)
.setUser(setting.getAndRemove(DSKeys.KEY_ALIAS_USER))
.setPass(setting.getAndRemove(DSKeys.KEY_ALIAS_PASSWORD))
.addSqlFilter(sqlLogFilter);
.setPass(setting.getAndRemove(DSKeys.KEY_ALIAS_PASSWORD));
// SQL日志
final SqlLogFilter sqlLogFilter = getSqlLogFilter(setting);
if(null != sqlLogFilter){
dbConfig.addSqlFilter(sqlLogFilter);
}
// 大小写等配置
final String caseInsensitive = setting.getAndRemove(DSKeys.KEY_CASE_INSENSITIVE);
if (StrUtil.isNotBlank(caseInsensitive)) {
dbConfig.setCaseInsensitive(Convert.toBoolean(caseInsensitive));
}
final String returnGeneratedKey = setting.getAndRemove(DSKeys.KEY_RETURN_GENERATED_KEY);
if (StrUtil.isNotBlank(returnGeneratedKey)) {
dbConfig.setReturnGeneratedKey(Convert.toBoolean(returnGeneratedKey));
}
// remarks等连接配置since 5.3.8
String connValue;
@ -174,6 +173,10 @@ public class SettingConfigParser implements ConfigParser {
private static SqlLogFilter getSqlLogFilter(final Setting setting) {
// 初始化SQL显示
final boolean isShowSql = Convert.toBoolean(setting.remove(DSKeys.KEY_SHOW_SQL), false);
if(!isShowSql){
return null;
}
final boolean isFormatSql = Convert.toBoolean(setting.remove(DSKeys.KEY_FORMAT_SQL), false);
final boolean isShowParams = Convert.toBoolean(setting.remove(DSKeys.KEY_SHOW_PARAMS), false);
String sqlLevelStr = setting.remove(DSKeys.KEY_SQL_LEVEL);

View File

@ -52,12 +52,13 @@ public interface Dialect extends Serializable {
* 构建用于插入的{@link PreparedStatement}<br>
* 用户实现需按照数据库方言格式{@link Entity}转换为带有占位符的SQL语句及参数列表
*
* @param returnGeneratedKey 是否返回自增主键
* @param conn 数据库连接对象
* @param entity 数据实体类包含表名
* @return PreparedStatement
* @throws DbException SQL执行异常
*/
PreparedStatement psForInsert(Connection conn, Entity entity) throws DbException;
PreparedStatement psForInsert(boolean returnGeneratedKey, Connection conn, Entity entity) throws DbException;
/**
* 构建用于批量插入的PreparedStatement<br>

View File

@ -17,7 +17,7 @@ import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.Entity;
import org.dromara.hutool.db.Page;
import org.dromara.hutool.db.StatementUtil;
import org.dromara.hutool.db.sql.StatementUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.dialect.Dialect;
import org.dromara.hutool.db.dialect.DialectName;
@ -60,10 +60,10 @@ public class AnsiSqlDialect implements Dialect {
}
@Override
public PreparedStatement psForInsert(final Connection conn, final Entity entity) {
public PreparedStatement psForInsert(final boolean returnGeneratedKey, final Connection conn, final Entity entity) {
final SqlBuilder insert = SqlBuilder.of(quoteWrapper).insert(entity, this.dialectName());
return StatementUtil.prepareStatement(this.dbConfig.isReturnGeneratedKey(), this.dbConfig, conn, insert.build(), insert.getParamValueArray());
return StatementUtil.prepareStatement(returnGeneratedKey, this.dbConfig, conn, insert.build(), insert.getParamValueArray());
}
@Override

View File

@ -17,7 +17,7 @@ import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.Entity;
import org.dromara.hutool.db.Page;
import org.dromara.hutool.db.StatementUtil;
import org.dromara.hutool.db.sql.StatementUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.dialect.DialectName;
import org.dromara.hutool.db.sql.SqlBuilder;

View File

@ -15,7 +15,7 @@ package org.dromara.hutool.db.dialect.impl;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.Entity;
import org.dromara.hutool.db.Page;
import org.dromara.hutool.db.StatementUtil;
import org.dromara.hutool.db.sql.StatementUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.dialect.DialectName;
import org.dromara.hutool.db.sql.QuoteWrapper;

View File

@ -43,7 +43,7 @@ public class PhoenixDialect extends AnsiSqlDialect {
public PreparedStatement psForUpdate(final Connection conn, final Entity entity, final Query query) throws DbException {
// Phoenix的插入更新语句是统一的统一使用upsert into关键字
// Phoenix只支持通过主键更新操作因此query无效自动根据entity中的主键更新
return super.psForInsert(conn, entity);
return super.psForInsert(true, conn, entity);
}
@Override
@ -54,6 +54,6 @@ public class PhoenixDialect extends AnsiSqlDialect {
@Override
public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) throws DbException {
// Phoenix只支持通过主键更新操作因此query无效自动根据entity中的主键更新
return psForInsert(conn, entity);
return psForInsert(true, conn, entity);
}
}

View File

@ -17,7 +17,7 @@ import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.CharUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.Entity;
import org.dromara.hutool.db.StatementUtil;
import org.dromara.hutool.db.sql.StatementUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.dialect.DialectName;
import org.dromara.hutool.db.sql.QuoteWrapper;

View File

@ -12,14 +12,14 @@
package org.dromara.hutool.db.ds;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.config.ConnectionConfig;
import javax.sql.DataSource;
import java.io.Serializable;
/**
* 多数据源{@link DataSource}工厂方法接口借助不同配置同一个工厂可以连接多个相同或不同的数据库但是连接池只能使用一种<br>
* 通过实现{@link #createDataSource(DbConfig)} 方法完成数据源的创建关系如下<br>
* 通过实现{@link #createDataSource(ConnectionConfig)} 方法完成数据源的创建关系如下<br>
* <pre>
* DSFactory
* _____________________|____________________
@ -47,5 +47,5 @@ public interface DSFactory extends Serializable {
* @param config 数据库配置
* @return {@link DataSource}
*/
DataSource createDataSource(DbConfig config);
DataSource createDataSource(ConnectionConfig<?> config);
}

View File

@ -80,7 +80,7 @@ public class DSPool implements Closeable {
*/
public DSPool(final ConfigParser configParser, final DSFactory factory) {
this.configParser = null != configParser ? configParser : SettingConfigParser.of();
this.factory = null != factory ? factory : SpiUtil.loadFirstAvailable(DSFactory.class);
this.factory = null != factory ? factory : DSUtil.getDefaultDsFactory();
this.pool = new SafeConcurrentHashMap<>();
}

View File

@ -12,7 +12,9 @@
package org.dromara.hutool.db.ds;
import org.dromara.hutool.core.spi.SpiUtil;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.log.LogUtil;
import javax.naming.InitialContext;
@ -28,6 +30,15 @@ import javax.sql.DataSource;
*/
public class DSUtil {
/**
* 获取默认数据源工厂
*
* @return 默认数据源工厂
*/
public static DSFactory getDefaultDsFactory() {
return SpiUtil.loadFirstAvailable(DSFactory.class);
}
/**
* 获得JNDI数据源
*
@ -57,6 +68,21 @@ public class DSUtil {
}
}
/**
* 根据已有配置文件创建数据源
*
* @param dbConfig 数据库配置
* @return 数据源
*/
public static DSWrapper createDS(final DbConfig dbConfig){
DSFactory dsFactory = dbConfig.getDsFactory();
if(null == dsFactory){
dsFactory = getDefaultDsFactory();
}
return DSWrapper.wrap(dsFactory.createDataSource(dbConfig), dbConfig);
}
/**
* 获得数据源<br>
* 使用默认配置文件的无分组配置

View File

@ -15,8 +15,8 @@ package org.dromara.hutool.db.ds.bee;
import cn.beecp.BeeDataSource;
import cn.beecp.BeeDataSourceConfig;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import javax.sql.DataSource;
@ -36,7 +36,7 @@ public class BeeDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final BeeDataSourceConfig beeConfig = new BeeDataSourceConfig(
config.getDriver(), config.getUrl(), config.getUser(), config.getPass());

View File

@ -15,8 +15,8 @@ package org.dromara.hutool.db.ds.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import javax.sql.DataSource;
@ -38,7 +38,7 @@ public class C3p0DSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setJdbcUrl(config.getUrl());

View File

@ -14,8 +14,8 @@ package org.dromara.hutool.db.ds.dbcp;
import org.apache.commons.dbcp2.BasicDataSource;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import javax.sql.DataSource;
@ -36,7 +36,7 @@ public class DbcpDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final BasicDataSource ds = new BasicDataSource();
ds.setUrl(config.getUrl());

View File

@ -15,8 +15,8 @@ package org.dromara.hutool.db.ds.druid;
import com.alibaba.druid.pool.DruidDataSource;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import javax.sql.DataSource;
@ -37,7 +37,7 @@ public class DruidDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final DruidDataSource ds = new DruidDataSource();
// 基本信息
@ -53,57 +53,60 @@ public class DruidDSFactory implements DSFactory {
}
// Druid连接池配置信息规范化属性名
final Props druidProps = new Props();
config.getPoolProps().forEach((key, value)-> druidProps.set(StrUtil.addPrefixIfNot(key.toString(), "druid."), value));
ds.configFromPropeties(druidProps);
final Properties poolProps = config.getPoolProps();
if(MapUtil.isNotEmpty(poolProps)){
final Props druidProps = new Props();
poolProps.forEach((key, value)-> druidProps.set(StrUtil.addPrefixIfNot(key.toString(), "druid."), value));
ds.configFromPropeties(druidProps);
//issue#I4ZKCW 某些非属性设置单独设置
// connectionErrorRetryAttempts
final String connectionErrorRetryAttemptsKey = "druid.connectionErrorRetryAttempts";
if(druidProps.containsKey(connectionErrorRetryAttemptsKey)){
ds.setConnectionErrorRetryAttempts(druidProps.getInt(connectionErrorRetryAttemptsKey));
}
// timeBetweenConnectErrorMillis
final String timeBetweenConnectErrorMillisKey = "druid.timeBetweenConnectErrorMillis";
if(druidProps.containsKey(timeBetweenConnectErrorMillisKey)){
ds.setTimeBetweenConnectErrorMillis(druidProps.getInt(timeBetweenConnectErrorMillisKey));
}
// breakAfterAcquireFailure
final String breakAfterAcquireFailureKey = "druid.breakAfterAcquireFailure";
if(druidProps.containsKey(breakAfterAcquireFailureKey)){
ds.setBreakAfterAcquireFailure(druidProps.getBool(breakAfterAcquireFailureKey));
}
//issue#I4ZKCW 某些非属性设置单独设置
// connectionErrorRetryAttempts
final String connectionErrorRetryAttemptsKey = "druid.connectionErrorRetryAttempts";
if(druidProps.containsKey(connectionErrorRetryAttemptsKey)){
ds.setConnectionErrorRetryAttempts(druidProps.getInt(connectionErrorRetryAttemptsKey));
}
// timeBetweenConnectErrorMillis
final String timeBetweenConnectErrorMillisKey = "druid.timeBetweenConnectErrorMillis";
if(druidProps.containsKey(timeBetweenConnectErrorMillisKey)){
ds.setTimeBetweenConnectErrorMillis(druidProps.getInt(timeBetweenConnectErrorMillisKey));
}
// breakAfterAcquireFailure
final String breakAfterAcquireFailureKey = "druid.breakAfterAcquireFailure";
if(druidProps.containsKey(breakAfterAcquireFailureKey)){
ds.setBreakAfterAcquireFailure(druidProps.getBool(breakAfterAcquireFailureKey));
}
// issue#I8STFC 补充
// validationQueryTimeout
final String validationQueryTimeout = "druid.validationQueryTimeout";
if(druidProps.containsKey(validationQueryTimeout)){
ds.setValidationQueryTimeout(druidProps.getInt(validationQueryTimeout));
}
// queryTimeout
final String queryTimeout = "druid.queryTimeout";
if(druidProps.containsKey(queryTimeout)){
ds.setQueryTimeout(druidProps.getInt(queryTimeout));
}
// connectTimeout
final String connectTimeout = "druid.connectTimeout";
if(druidProps.containsKey(connectTimeout)){
ds.setConnectTimeout(druidProps.getInt(connectTimeout));
}
// socketTimeout
final String socketTimeout = "druid.socketTimeout";
if(druidProps.containsKey(socketTimeout)){
ds.setSocketTimeout(druidProps.getInt(socketTimeout));
}
// transactionQueryTimeout
final String transactionQueryTimeout = "druid.transactionQueryTimeout";
if(druidProps.containsKey(transactionQueryTimeout)){
ds.setTransactionQueryTimeout(druidProps.getInt(transactionQueryTimeout));
}
// loginTimeout
final String loginTimeout = "druid.loginTimeout";
if(druidProps.containsKey(loginTimeout)){
ds.setLoginTimeout(druidProps.getInt(loginTimeout));
// issue#I8STFC 补充
// validationQueryTimeout
final String validationQueryTimeout = "druid.validationQueryTimeout";
if(druidProps.containsKey(validationQueryTimeout)){
ds.setValidationQueryTimeout(druidProps.getInt(validationQueryTimeout));
}
// queryTimeout
final String queryTimeout = "druid.queryTimeout";
if(druidProps.containsKey(queryTimeout)){
ds.setQueryTimeout(druidProps.getInt(queryTimeout));
}
// connectTimeout
final String connectTimeout = "druid.connectTimeout";
if(druidProps.containsKey(connectTimeout)){
ds.setConnectTimeout(druidProps.getInt(connectTimeout));
}
// socketTimeout
final String socketTimeout = "druid.socketTimeout";
if(druidProps.containsKey(socketTimeout)){
ds.setSocketTimeout(druidProps.getInt(socketTimeout));
}
// transactionQueryTimeout
final String transactionQueryTimeout = "druid.transactionQueryTimeout";
if(druidProps.containsKey(transactionQueryTimeout)){
ds.setTransactionQueryTimeout(druidProps.getInt(transactionQueryTimeout));
}
// loginTimeout
final String loginTimeout = "druid.loginTimeout";
if(druidProps.containsKey(loginTimeout)){
ds.setLoginTimeout(druidProps.getInt(loginTimeout));
}
}
// 检查关联配置在用户未设置某项配置时设置默认值

View File

@ -14,11 +14,13 @@ package org.dromara.hutool.db.ds.hikari;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import javax.sql.DataSource;
import java.util.Properties;
/**
* HikariCP数据源工厂类
@ -35,7 +37,7 @@ public class HikariDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final Props props = new Props();
// 基本信息
@ -54,11 +56,17 @@ public class HikariDSFactory implements DSFactory {
}
// 连接池信息
props.putAll(config.getPoolProps());
final Properties poolProps = config.getPoolProps();
if(MapUtil.isNotEmpty(poolProps)){
props.putAll(poolProps);
}
final HikariConfig hikariConfig = new HikariConfig(props);
// 连接信息
hikariConfig.setDataSourceProperties(config.getConnProps());
final Properties connProps = config.getConnProps();
if(MapUtil.isNotEmpty(connProps)){
hikariConfig.setDataSourceProperties(connProps);
}
return new HikariDataSource(hikariConfig);
}

View File

@ -14,9 +14,9 @@ package org.dromara.hutool.db.ds.jndi;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.ds.DSUtil;
import org.dromara.hutool.db.config.DbConfig;
import javax.sql.DataSource;
@ -40,7 +40,7 @@ public class JndiDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
final String jndiName = config.getPoolProps().getProperty("jndi");
if (StrUtil.isEmpty(jndiName)) {
throw new DbException("No setting name [jndi] for this group.");

View File

@ -15,7 +15,7 @@ package org.dromara.hutool.db.ds.pooled;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.pool.Poolable;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.setting.props.Props;
import java.sql.Connection;
@ -41,7 +41,7 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
* @param config 数据库配置
* @param dataSource 数据源
*/
public PooledConnection(final DbConfig config, final PooledDataSource dataSource) {
public PooledConnection(final ConnectionConfig<?> config, final PooledDataSource dataSource) {
final Props info = new Props();
final String user = config.getUser();
if (user != null) {

View File

@ -12,8 +12,8 @@
package org.dromara.hutool.db.ds.pooled;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import javax.sql.DataSource;
@ -32,7 +32,7 @@ public class PooledDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
return new PooledDataSource(config);
}
}

View File

@ -18,7 +18,7 @@ import org.dromara.hutool.core.pool.ObjectPool;
import org.dromara.hutool.core.pool.partition.PartitionObjectPool;
import org.dromara.hutool.core.pool.partition.PartitionPoolConfig;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.simple.AbstractDataSource;
import org.dromara.hutool.setting.props.Props;
@ -45,7 +45,7 @@ public class PooledDataSource extends AbstractDataSource {
*
* @param config 数据库池配置
*/
public PooledDataSource(final DbConfig config) {
public PooledDataSource(final ConnectionConfig<?> config) {
final Props poolProps = Props.of(config.getPoolProps());
this.maxWait = poolProps.getInt(KEY_MAX_WAIT, 6000);
@ -89,7 +89,7 @@ public class PooledDataSource extends AbstractDataSource {
* @param config 数据库配置
* @return {@link ObjectFactory}
*/
private ObjectFactory<Connection> createConnFactory(final DbConfig config) {
private ObjectFactory<Connection> createConnFactory(final ConnectionConfig<?> config) {
return new ObjectFactory<Connection>() {
@Override
public Connection create() {

View File

@ -12,8 +12,8 @@
package org.dromara.hutool.db.ds.simple;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import javax.sql.DataSource;
@ -32,7 +32,7 @@ public class SimpleDSFactory implements DSFactory {
}
@Override
public DataSource createDataSource(final DbConfig config) {
public DataSource createDataSource(final ConnectionConfig<?> config) {
return new SimpleDataSource(config);
}
}

View File

@ -13,7 +13,7 @@
package org.dromara.hutool.db.ds.simple;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.setting.props.Props;
import java.sql.Connection;
@ -32,20 +32,20 @@ public class SimpleDataSource extends AbstractDataSource {
/** 默认的数据库连接配置文件路径 */
public final static String DEFAULT_DB_CONFIG_PATH = "config/db.setting";
private final DbConfig config;
private final ConnectionConfig<?> config;
/**
* 构造
*
* @param config 数据库连接配置
*/
public SimpleDataSource(final DbConfig config) {
public SimpleDataSource(final ConnectionConfig<?> config) {
this.config = config;
}
@Override
public Connection getConnection() throws SQLException {
final DbConfig config = this.config;
final ConnectionConfig<?> config = this.config;
final Props info = new Props();
final String user = config.getUser();

View File

@ -14,10 +14,13 @@ package org.dromara.hutool.db.ds.tomcat;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.db.config.ConnectionConfig;
import org.dromara.hutool.db.ds.DSFactory;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.setting.props.Props;
import java.util.Properties;
/**
* Tomcat-Jdbc-Pool数据源工厂类
*
@ -32,7 +35,7 @@ public class TomcatDSFactory implements DSFactory {
}
@Override
public javax.sql.DataSource createDataSource(final DbConfig config) {
public javax.sql.DataSource createDataSource(final ConnectionConfig<?> config) {
final PoolProperties poolProps = new PoolProperties();
// 基本配置
@ -42,7 +45,10 @@ public class TomcatDSFactory implements DSFactory {
poolProps.setPassword(config.getPass());
// 连接配置
poolProps.setDbProperties(config.getConnProps());
final Properties connProps = config.getConnProps();
if(MapUtil.isNotEmpty(connProps)){
poolProps.setDbProperties(connProps);
}
// 连接池相关参数
Props.of(config.getPoolProps()).toBean(poolProps);

View File

@ -16,7 +16,6 @@ import org.dromara.hutool.core.collection.iter.ArrayIter;
import org.dromara.hutool.core.func.SerFunction;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.StatementUtil;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.handler.RsHandler;

View File

@ -10,19 +10,16 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.db;
package org.dromara.hutool.db.sql;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.collection.iter.ArrayIter;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.db.DbException;
import org.dromara.hutool.db.config.DbConfig;
import org.dromara.hutool.db.handler.ResultSetUtil;
import org.dromara.hutool.db.handler.RsHandler;
import org.dromara.hutool.db.sql.SqlBuilder;
import org.dromara.hutool.db.sql.StatementBuilder;
import org.dromara.hutool.db.sql.StatementWrapper;
import org.dromara.hutool.db.sql.filter.SqlLogFilter;
import java.sql.*;
import java.util.List;

View File

@ -0,0 +1,31 @@
package org.dromara.hutool.db;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.db.config.DbConfig;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class IssueI8UTGPTest {
@Test
void customSqlLogTest() {
final AtomicBoolean isFilterValid = new AtomicBoolean(false);
final DbConfig dbConfig = DbConfig.of()
.setUrl("jdbc:sqlite:test.db")
.addSqlFilter((conn, boundSql, returnGeneratedKey) -> {
isFilterValid.set(true);
Console.log("Custom log: {}", boundSql.getSql());
});
final Db db = Db.of(dbConfig);
final List<Entity> find = db.query("select * from user where age = ?", 18);
Assertions.assertEquals("王五", find.get(0).get("name"));
Assertions.assertTrue(isFilterValid.get());
}
}