增加DataNativeSqlParser功能
This commit is contained in:
@@ -39,6 +39,7 @@ module org.redkale {
|
|||||||
uses org.redkale.mq.MessageAgentProvider;
|
uses org.redkale.mq.MessageAgentProvider;
|
||||||
uses org.redkale.source.CacheSourceProvider;
|
uses org.redkale.source.CacheSourceProvider;
|
||||||
uses org.redkale.source.DataSourceProvider;
|
uses org.redkale.source.DataSourceProvider;
|
||||||
|
uses org.redkale.source.DataNativeSqlParserProvider;
|
||||||
uses org.redkale.util.ResourceAnnotationProvider;
|
uses org.redkale.util.ResourceAnnotationProvider;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,9 @@ public final class Application {
|
|||||||
|
|
||||||
private final ReentrantLock dataSourceLock = new ReentrantLock();
|
private final ReentrantLock dataSourceLock = new ReentrantLock();
|
||||||
|
|
||||||
|
//原生sql解析器
|
||||||
|
private DataNativeSqlParser nativeSqlParser;
|
||||||
|
|
||||||
//NodeServer 资源, 顺序必须是sncps, others, watchs
|
//NodeServer 资源, 顺序必须是sncps, others, watchs
|
||||||
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@@ -580,6 +583,23 @@ public final class Application {
|
|||||||
this.excludelibs = excludelib0;
|
this.excludelibs = excludelib0;
|
||||||
this.clusterAgent = cluster;
|
this.clusterAgent = cluster;
|
||||||
this.messageAgents = mqs;
|
this.messageAgents = mqs;
|
||||||
|
{ //加载原生sql解析器
|
||||||
|
Iterator<DataNativeSqlParserProvider> it = ServiceLoader.load(DataNativeSqlParserProvider.class, classLoader).iterator();
|
||||||
|
RedkaleClassLoader.putServiceLoader(DataNativeSqlParserProvider.class);
|
||||||
|
List<DataNativeSqlParserProvider> providers = new ArrayList<>();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
DataNativeSqlParserProvider provider = it.next();
|
||||||
|
if (provider != null && provider.acceptsConf(null)) {
|
||||||
|
RedkaleClassLoader.putReflectionPublicConstructors(provider.getClass(), provider.getClass().getName());
|
||||||
|
providers.add(provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (DataNativeSqlParserProvider provider : InstanceProvider.sort(providers)) {
|
||||||
|
this.nativeSqlParser = provider.createInstance();
|
||||||
|
this.resourceFactory.register(DataNativeSqlParser.class, this.nativeSqlParser);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (compileMode || this.classLoader instanceof RedkaleClassLoader.RedkaleCacheClassLoader) {
|
if (compileMode || this.classLoader instanceof RedkaleClassLoader.RedkaleCacheClassLoader) {
|
||||||
this.serverClassLoader = this.classLoader;
|
this.serverClassLoader = this.classLoader;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
|||||||
@Resource(name = RESNAME_APP_EXECUTOR, required = false)
|
@Resource(name = RESNAME_APP_EXECUTOR, required = false)
|
||||||
protected ExecutorService workExecutor;
|
protected ExecutorService workExecutor;
|
||||||
|
|
||||||
|
@Resource(required = false)
|
||||||
|
protected DataNativeSqlParser nativeSqlParser;
|
||||||
|
|
||||||
protected BiFunction<EntityInfo, Object, CharSequence> sqlFormatter;
|
protected BiFunction<EntityInfo, Object, CharSequence> sqlFormatter;
|
||||||
|
|
||||||
protected BiConsumer errorCompleteConsumer = (r, t) -> {
|
protected BiConsumer errorCompleteConsumer = (r, t) -> {
|
||||||
@@ -639,6 +642,13 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
|||||||
return getSQLAttrValue(info, attr, val);
|
return getSQLAttrValue(info, attr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected DataNativeSqlParser.NativeSqlInfo nativeParse(String nativeSql, Map<String, Object> params) {
|
||||||
|
if (nativeSqlParser == null) {
|
||||||
|
throw new SourceException("not found DataNativeSqlParser instance");
|
||||||
|
}
|
||||||
|
return nativeSqlParser.parse(nativeSql, params == null ? Collections.emptyMap() : params);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy(AnyValue config) {
|
public void destroy(AnyValue config) {
|
||||||
super.destroy(config);
|
super.destroy(config);
|
||||||
@@ -3276,4 +3286,5 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
|||||||
entitys.add(entity);
|
entitys.add(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.redkale.annotation.*;
|
|||||||
import org.redkale.annotation.ResourceListener;
|
import org.redkale.annotation.ResourceListener;
|
||||||
import org.redkale.annotation.ResourceType;
|
import org.redkale.annotation.ResourceType;
|
||||||
import org.redkale.service.Local;
|
import org.redkale.service.Local;
|
||||||
|
import org.redkale.source.DataNativeSqlParser.NativeSqlInfo;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2481,19 +2482,6 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
|||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
|
||||||
* 通常用于复杂的更新操作 <br>
|
|
||||||
*
|
|
||||||
* @param sql SQL语句
|
|
||||||
*
|
|
||||||
* @return 结果数组
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int nativeUpdate(String sql) {
|
|
||||||
return nativeUpdates(new String[]{sql})[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
||||||
* 通常用于复杂的更新操作 <br>
|
* 通常用于复杂的更新操作 <br>
|
||||||
@@ -2515,7 +2503,7 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
|||||||
final int[] rs = new int[sqls.length];
|
final int[] rs = new int[sqls.length];
|
||||||
int i = -1;
|
int i = -1;
|
||||||
for (String sql : sqls) {
|
for (String sql : sqls) {
|
||||||
rs[++i] = stmt.execute(sql) ? 1 : 0;
|
rs[++i] = stmt.executeUpdate(sql);
|
||||||
}
|
}
|
||||||
conn.offerUpdateStatement(stmt);
|
conn.offerUpdateStatement(stmt);
|
||||||
conn.commit();
|
conn.commit();
|
||||||
@@ -2534,6 +2522,57 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
||||||
|
* 通常用于复杂的更新操作 <br>
|
||||||
|
*
|
||||||
|
* @param sql SQL语句
|
||||||
|
*
|
||||||
|
* @return 结果数组
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int nativeUpdate(String sql) {
|
||||||
|
return nativeUpdates(new String[]{sql})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nativeUpdate(String sql, Map<String, Object> params) {
|
||||||
|
NativeSqlInfo sinfo = super.nativeParse(sql, params);
|
||||||
|
final long s = System.currentTimeMillis();
|
||||||
|
SourceConnection conn = writePool.pollConnection();
|
||||||
|
try {
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
int rs;
|
||||||
|
if (sinfo.isEmptyNamed()) {
|
||||||
|
final Statement stmt = conn.createUpdateStatement();
|
||||||
|
rs = stmt.executeUpdate(sinfo.nativeSql);
|
||||||
|
conn.offerUpdateStatement(stmt);
|
||||||
|
} else {
|
||||||
|
final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql);
|
||||||
|
Map<String, Object> paramValues = sinfo.getParamValues();
|
||||||
|
int index = 0;
|
||||||
|
for (String n : sinfo.getParamNames()) {
|
||||||
|
prestmt.setObject(++index, paramValues.get(n));
|
||||||
|
}
|
||||||
|
rs = prestmt.executeUpdate();
|
||||||
|
conn.offerUpdateStatement(prestmt);
|
||||||
|
}
|
||||||
|
conn.commit();
|
||||||
|
slowLog(s, sinfo.nativeSql);
|
||||||
|
return rs;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
try {
|
||||||
|
conn.rollback();
|
||||||
|
} catch (SQLException se) {
|
||||||
|
}
|
||||||
|
throw new SourceException(e);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
writePool.offerConnection(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 直接本地执行SQL语句进行查询,远程模式不可用 <br>
|
* 直接本地执行SQL语句进行查询,远程模式不可用 <br>
|
||||||
* 通常用于复杂的关联查询 <br>
|
* 通常用于复杂的关联查询 <br>
|
||||||
@@ -2571,14 +2610,49 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nativeUpdate(String sql, Map<String, Object> params) {
|
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params) {
|
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
NativeSqlInfo sinfo = super.nativeParse(sql, params);
|
||||||
|
final long s = System.currentTimeMillis();
|
||||||
|
final SourceConnection conn = readPool.pollConnection();
|
||||||
|
try {
|
||||||
|
if (logger.isLoggable(Level.FINEST)) {
|
||||||
|
logger.finest("executeQuery sql=" + sinfo.nativeSql);
|
||||||
|
}
|
||||||
|
V rs;
|
||||||
|
if (sinfo.isEmptyNamed()) {
|
||||||
|
final Statement stmt = conn.createQueryStatement();
|
||||||
|
if (consumer != null) {
|
||||||
|
consumer.accept(conn, stmt);
|
||||||
|
}
|
||||||
|
ResultSet set = stmt.executeQuery(sql);
|
||||||
|
rs = handler.apply(createDataResultSet(null, set));
|
||||||
|
set.close();
|
||||||
|
conn.offerQueryStatement(stmt);
|
||||||
|
} else {
|
||||||
|
final PreparedStatement prestmt = conn.prepareQueryStatement(sinfo.nativeSql);
|
||||||
|
Map<String, Object> paramValues = sinfo.getParamValues();
|
||||||
|
int index = 0;
|
||||||
|
for (String n : sinfo.getParamNames()) {
|
||||||
|
prestmt.setObject(++index, paramValues.get(n));
|
||||||
|
}
|
||||||
|
if (consumer != null) {
|
||||||
|
consumer.accept(conn, prestmt);
|
||||||
|
}
|
||||||
|
ResultSet set = prestmt.executeQuery(sql);
|
||||||
|
rs = handler.apply(createDataResultSet(null, set));
|
||||||
|
set.close();
|
||||||
|
conn.offerQueryStatement(prestmt);
|
||||||
|
}
|
||||||
|
slowLog(s, sql);
|
||||||
|
return rs;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new SourceException(ex);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
readPool.offerConnection(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
74
src/main/java/org/redkale/source/DataNativeSqlParser.java
Normal file
74
src/main/java/org/redkale/source/DataNativeSqlParser.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.source;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import org.redkale.convert.ConvertDisabled;
|
||||||
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 原生的sql解析器
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public interface DataNativeSqlParser {
|
||||||
|
|
||||||
|
NativeSqlInfo parse(String nativeSql, Map<String, Object> params);
|
||||||
|
|
||||||
|
public static class NativeSqlInfo {
|
||||||
|
|
||||||
|
//根据参数值集合重新生成的可执行的sql
|
||||||
|
protected String nativeSql;
|
||||||
|
|
||||||
|
//需要预编译的参数名
|
||||||
|
protected List<String> paramNames;
|
||||||
|
|
||||||
|
//参数值集合
|
||||||
|
protected Map<String, Object> paramValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否带有参数
|
||||||
|
*
|
||||||
|
* @return 是否带有参数
|
||||||
|
*/
|
||||||
|
@ConvertDisabled
|
||||||
|
public boolean isEmptyNamed() {
|
||||||
|
return paramNames == null || paramNames.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNativeSql() {
|
||||||
|
return nativeSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNativeSql(String nativeSql) {
|
||||||
|
this.nativeSql = nativeSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getParamNames() {
|
||||||
|
return paramNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParamNames(List<String> paramNames) {
|
||||||
|
this.paramNames = paramNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getParamValues() {
|
||||||
|
return paramValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParamValues(Map<String, Object> paramValues) {
|
||||||
|
this.paramValues = paramValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonConvert.root().convertTo(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.source;
|
||||||
|
|
||||||
|
import org.redkale.util.InstanceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 自定义的DataNativeSqlParser加载器, 如果标记@Priority加载器的优先级需要大于1000, 1000以下预留给官方加载器
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public interface DataNativeSqlParserProvider extends InstanceProvider<DataNativeSqlParser> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,16 +21,57 @@ import org.redkale.util.Copier;
|
|||||||
*/
|
*/
|
||||||
public interface DataSqlSource extends DataSource {
|
public interface DataSqlSource extends DataSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行多条原生无参数的sql
|
||||||
|
*
|
||||||
|
* @param sql 无参数的sql语句
|
||||||
|
*
|
||||||
|
* @return 执行条数
|
||||||
|
*/
|
||||||
public int[] nativeUpdates(String... sqls);
|
public int[] nativeUpdates(String... sqls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行原生无参数的sql
|
||||||
|
*
|
||||||
|
* @param sql 无参数的sql语句
|
||||||
|
*
|
||||||
|
* @return 执行条数
|
||||||
|
*/
|
||||||
public int nativeUpdate(String sql);
|
public int nativeUpdate(String sql);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行原生带参数的sql
|
||||||
|
*
|
||||||
|
* @param sql 带参数的sql语句
|
||||||
|
* @param params 参数值集合
|
||||||
|
*
|
||||||
|
* @return 执行条数
|
||||||
|
*/
|
||||||
public int nativeUpdate(String sql, Map<String, Object> params);
|
public int nativeUpdate(String sql, Map<String, Object> params);
|
||||||
|
|
||||||
//BiConsumer 参数1: connection, 参数2: statement
|
/**
|
||||||
|
* 通过原生的sql查询结果
|
||||||
|
*
|
||||||
|
* @param <V> 泛型
|
||||||
|
* @param sql 无参数的sql语句
|
||||||
|
* @param consumer BiConsumer 参数1: connection, 参数2: statement
|
||||||
|
* @param handler DataResultSet的回调函数
|
||||||
|
*
|
||||||
|
* @return 结果对象
|
||||||
|
*/
|
||||||
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler);
|
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler);
|
||||||
|
|
||||||
//BiConsumer 参数1: connection, 参数2: statement
|
/**
|
||||||
|
* 通过原生带参数的sql查询结果
|
||||||
|
*
|
||||||
|
* @param <V> 泛型
|
||||||
|
* @param sql 带参数的sql语句
|
||||||
|
* @param consumer BiConsumer 参数1: connection, 参数2: statement
|
||||||
|
* @param handler DataResultSet的回调函数
|
||||||
|
* @param params 参数值集合
|
||||||
|
*
|
||||||
|
* @return 结果对象
|
||||||
|
*/
|
||||||
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params);
|
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params);
|
||||||
|
|
||||||
//----------------------------- 无参数 -----------------------------
|
//----------------------------- 无参数 -----------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user