增加DataNativeSqlParser功能
This commit is contained in:
@@ -39,6 +39,7 @@ module org.redkale {
|
||||
uses org.redkale.mq.MessageAgentProvider;
|
||||
uses org.redkale.source.CacheSourceProvider;
|
||||
uses org.redkale.source.DataSourceProvider;
|
||||
uses org.redkale.source.DataNativeSqlParserProvider;
|
||||
uses org.redkale.util.ResourceAnnotationProvider;
|
||||
|
||||
}
|
||||
|
||||
@@ -157,6 +157,9 @@ public final class Application {
|
||||
|
||||
private final ReentrantLock dataSourceLock = new ReentrantLock();
|
||||
|
||||
//原生sql解析器
|
||||
private DataNativeSqlParser nativeSqlParser;
|
||||
|
||||
//NodeServer 资源, 顺序必须是sncps, others, watchs
|
||||
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -580,6 +583,23 @@ public final class Application {
|
||||
this.excludelibs = excludelib0;
|
||||
this.clusterAgent = cluster;
|
||||
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) {
|
||||
this.serverClassLoader = this.classLoader;
|
||||
} else {
|
||||
|
||||
@@ -65,6 +65,9 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
||||
@Resource(name = RESNAME_APP_EXECUTOR, required = false)
|
||||
protected ExecutorService workExecutor;
|
||||
|
||||
@Resource(required = false)
|
||||
protected DataNativeSqlParser nativeSqlParser;
|
||||
|
||||
protected BiFunction<EntityInfo, Object, CharSequence> sqlFormatter;
|
||||
|
||||
protected BiConsumer errorCompleteConsumer = (r, t) -> {
|
||||
@@ -639,6 +642,13 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
||||
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
|
||||
public void destroy(AnyValue config) {
|
||||
super.destroy(config);
|
||||
@@ -3276,4 +3286,5 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
||||
entitys.add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.redkale.annotation.*;
|
||||
import org.redkale.annotation.ResourceListener;
|
||||
import org.redkale.annotation.ResourceType;
|
||||
import org.redkale.service.Local;
|
||||
import org.redkale.source.DataNativeSqlParser.NativeSqlInfo;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
@@ -2481,19 +2482,6 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
||||
return rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
||||
* 通常用于复杂的更新操作 <br>
|
||||
*
|
||||
* @param sql SQL语句
|
||||
*
|
||||
* @return 结果数组
|
||||
*/
|
||||
@Override
|
||||
public int nativeUpdate(String sql) {
|
||||
return nativeUpdates(new String[]{sql})[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接本地执行SQL语句进行增删改操作,远程模式不可用 <br>
|
||||
* 通常用于复杂的更新操作 <br>
|
||||
@@ -2515,7 +2503,7 @@ public class DataJdbcSource extends AbstractDataSqlSource {
|
||||
final int[] rs = new int[sqls.length];
|
||||
int i = -1;
|
||||
for (String sql : sqls) {
|
||||
rs[++i] = stmt.execute(sql) ? 1 : 0;
|
||||
rs[++i] = stmt.executeUpdate(sql);
|
||||
}
|
||||
conn.offerUpdateStatement(stmt);
|
||||
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>
|
||||
* 通常用于复杂的关联查询 <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
|
||||
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
|
||||
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 执行多条原生无参数的sql
|
||||
*
|
||||
* @param sql 无参数的sql语句
|
||||
*
|
||||
* @return 执行条数
|
||||
*/
|
||||
public int[] nativeUpdates(String... sqls);
|
||||
|
||||
/**
|
||||
* 执行原生无参数的sql
|
||||
*
|
||||
* @param sql 无参数的sql语句
|
||||
*
|
||||
* @return 执行条数
|
||||
*/
|
||||
public int nativeUpdate(String sql);
|
||||
|
||||
/**
|
||||
* 执行原生带参数的sql
|
||||
*
|
||||
* @param sql 带参数的sql语句
|
||||
* @param params 参数值集合
|
||||
*
|
||||
* @return 执行条数
|
||||
*/
|
||||
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);
|
||||
|
||||
//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);
|
||||
|
||||
//----------------------------- 无参数 -----------------------------
|
||||
|
||||
Reference in New Issue
Block a user