Commit 7a83fd3f authored by 雍欢's avatar 雍欢

easysearch支持切换SQL方言

parent 37c6c6d4
package com.huigou.properties; package com.huigou.properties;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import com.huigou.util.ConfigFileVersion; import com.huigou.util.ConfigFileVersion;
...@@ -21,7 +18,7 @@ public class PropertiesModel implements Serializable, ConfigFileVersion { ...@@ -21,7 +18,7 @@ public class PropertiesModel implements Serializable, ConfigFileVersion {
private Long versions; private Long versions;
private String configFilePath; private List<String> configFilePaths;
public PropertiesModel(Properties props) { public PropertiesModel(Properties props) {
this.props = props; this.props = props;
...@@ -37,12 +34,21 @@ public class PropertiesModel implements Serializable, ConfigFileVersion { ...@@ -37,12 +34,21 @@ public class PropertiesModel implements Serializable, ConfigFileVersion {
} }
public void setConfigFilePath(String configFilePath) { public void setConfigFilePath(String configFilePath) {
this.configFilePath = configFilePath; this.configFilePaths = Collections.singletonList(configFilePath);
} }
@Override @Override
public String getFilePath() { public String getFilePath() {
return configFilePath; return configFilePaths.get(0);
}
public void setConfigFilePaths(List<String> configFilePaths) {
this.configFilePaths = configFilePaths;
}
@Override
public List<String> getFilePaths() {
return configFilePaths;
} }
public Properties getProps() { public Properties getProps() {
......
package com.huigou.util; package com.huigou.util;
import java.util.List;
public interface ConfigFileVersion { public interface ConfigFileVersion {
/** /**
* 获取对象版本号 * 获取对象版本号
* *
* @return * @return
*/ */
Long getVersion(); Long getVersion();
/** /**
* 获取配置文件路径 * 获取配置文件路径
* *
* @return * @deprecated 请使用 {@link #getFilePaths()} 替代
*/ */
@Deprecated
String getFilePath(); String getFilePath();
/**
* @since 1.1.3
*/
List<String> getFilePaths();
} }
package com.huigou.util; package com.huigou.util;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.huigou.exception.ApplicationException;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import com.huigou.exception.NotFoundException; import com.huigou.exception.NotFoundException;
import com.huigou.exception.ResourceLoadException; import com.huigou.exception.ResourceLoadException;
import org.springframework.core.io.Resource;
/** /**
* 资源文件加载管理类 * 资源文件加载管理类
* *
* @author xx
* @param <T> * @param <T>
* @author xx
*/ */
public abstract class ResourceLoadManager<T> { public abstract class ResourceLoadManager<T> {
/** /**
* 加载配置资源文件 * 加载配置资源文件
* *
* @param path * @param path 路径
* 路径
* @return * @return
* @throws NotFoundException * @throws NotFoundException
*/ */
...@@ -27,7 +32,7 @@ public abstract class ResourceLoadManager<T> { ...@@ -27,7 +32,7 @@ public abstract class ResourceLoadManager<T> {
/** /**
* 从classpath(jar包等)中找到目标资源 * 从classpath(jar包等)中找到目标资源
* *
* @param name * @param name
* @return * @return
* @throws IOException * @throws IOException
...@@ -38,13 +43,49 @@ public abstract class ResourceLoadManager<T> { ...@@ -38,13 +43,49 @@ public abstract class ResourceLoadManager<T> {
/** /**
* 获取配置文件最后修改时间 * 获取配置文件最后修改时间
* *
* @param name * @param name 文件名
* 文件名
* @return * @return
* @throws IOException * @throws IOException
*/ */
public static Long getLastModified(String name) throws IOException { public static Long getLastModified(String name) throws IOException {
return new ClassPathResource(name).lastModified(); return new ClassPathResource(name).lastModified();
} }
/**
* 获取最大的修改时间。
*
* @param resources 资源。
* @return 最大的修改时间
* @throws ApplicationException
* @since 1.1.3
*/
public static long maxLastModified(Collection<String> resources) {
List<Resource> rs = resources.stream()
.filter(Objects::nonNull)
.map(ClassPathResource::new)
.collect(Collectors.toList());
return maxLastModified(rs);
}
/**
* 获取最大的修改时间。
*
* @param resources 资源。
* @return 最大的修改时间
* @throws ApplicationException
* @since 1.1.3
*/
public static long maxLastModified(List<Resource> resources) {
return resources.stream()
.filter(Objects::nonNull)
.filter(Resource::exists)
.mapToLong(r -> {
try {
return r.lastModified();
} catch (IOException ioe) {
throw new ApplicationException(ioe);
}
}).max().getAsLong();
}
} }
...@@ -280,6 +280,7 @@ public enum Dialect { ...@@ -280,6 +280,7 @@ public enum Dialect {
* @return String * @return String
*/ */
public static String getTotalSql(String sql) { public static String getTotalSql(String sql) {
// TODO 这里写表别名 t_ 会影响easysearch的分页查询
return "select count(0) from (" + sql + ") t_"; return "select count(0) from (" + sql + ") t_";
} }
......
...@@ -5,10 +5,7 @@ import com.huigou.uasp.bmp.query.QueryMappingsDocument.QueryMappings; ...@@ -5,10 +5,7 @@ import com.huigou.uasp.bmp.query.QueryMappingsDocument.QueryMappings;
import com.huigou.util.ConfigFileVersion; import com.huigou.util.ConfigFileVersion;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -37,7 +34,7 @@ public class QueryXmlModel implements Serializable, ConfigFileVersion { ...@@ -37,7 +34,7 @@ public class QueryXmlModel implements Serializable, ConfigFileVersion {
*/ */
private Long version; private Long version;
private String configFilePath; private List<String> configFilePaths;
public QueryXmlModel(QueryMappings queryMappings, QueryMappings dialectQueryMappings) { public QueryXmlModel(QueryMappings queryMappings, QueryMappings dialectQueryMappings) {
if (queryMappings != null) { if (queryMappings != null) {
...@@ -93,11 +90,19 @@ public class QueryXmlModel implements Serializable, ConfigFileVersion { ...@@ -93,11 +90,19 @@ public class QueryXmlModel implements Serializable, ConfigFileVersion {
@Override @Override
public String getFilePath() { public String getFilePath() {
return configFilePath; return configFilePaths.get(0);
} }
public void setConfigFilePath(String configFilePath) { public void setConfigFilePath(String configFilePath) {
this.configFilePath = configFilePath; this.configFilePaths = Collections.singletonList(configFilePath);
} }
@Override
public List<String> getFilePaths() {
return configFilePaths;
}
public void setConfigFilePaths(List<String> configFilePaths) {
this.configFilePaths = configFilePaths;
}
} }
package com.huigou.uasp.bmp.common.easysearch; package com.huigou.uasp.bmp.common.easysearch;
import java.io.IOException; import com.huigou.exception.ApplicationException;
import java.io.InputStream;
import org.springframework.core.io.ClassPathResource;
import com.huigou.exception.NotFoundException; import com.huigou.exception.NotFoundException;
import com.huigou.exception.ResourceLoadException; import com.huigou.exception.ResourceLoadException;
import com.huigou.uasp.bmp.common.easysearch.domain.EasySearchLoadInterface; import com.huigou.uasp.bmp.common.easysearch.domain.EasySearchLoadInterface;
import com.huigou.uasp.bmp.common.easysearch.domain.model.EasySearchMappingModel; import com.huigou.uasp.bmp.common.easysearch.domain.model.EasySearchMappingModel;
import com.huigou.uasp.bmp.easysearch.EasySearchMappingsDocument; import com.huigou.uasp.bmp.easysearch.EasySearchMappingsDocument;
import com.huigou.util.ResourceLoadManager; import com.huigou.util.ResourceLoadManager;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.xmlbeans.XmlException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* 快捷查询配置文件加载管理类 * 快捷查询配置文件加载管理类
* *
* @author xx * @author xx
*/ */
public class EasySearchManager extends ResourceLoadManager<EasySearchMappingModel> implements EasySearchLoadInterface { public class EasySearchManager extends ResourceLoadManager<EasySearchMappingModel> implements EasySearchLoadInterface {
/**
* SQL 方言。
*
* @since 1.1.3
*/
private String sqlDialect;
/**
* 设置SQL方言。
*
* @since 1.1.3
*/
public void setSqlDialect(String sqlDialect) {
this.sqlDialect = sqlDialect;
}
/** /**
* 加载配置文件 * 加载配置文件
*/ */
@Override
public EasySearchMappingModel loadConfigFile(String type) throws NotFoundException { public EasySearchMappingModel loadConfigFile(String type) throws NotFoundException {
String path = String.format(XML_PATH, type); List<String> paths = new ArrayList<>(2);
InputStream inputStream = null; // 方言xml放在最前面,从而达到优先使用方言xml的目的
if (StringUtils.isNotBlank(sqlDialect)) {
paths.add(String.format(DIALECT_XML_PATH, sqlDialect, type));
}
String defaultPath = String.format(XML_PATH, type);
paths.add(defaultPath);
List<InputStream> xmlStreams = Collections.emptyList();
try { try {
ClassPathResource resource = getResource(path); List<Resource> resources = paths.stream()
inputStream = resource.getInputStream(); .map(ClassPathResource::new)
EasySearchMappingsDocument doc = EasySearchMappingsDocument.Factory.parse(inputStream); .filter(Resource::exists)
EasySearchMappingModel mappingModel = new EasySearchMappingModel(doc.getEasySearchMappings()); .collect(Collectors.toList());
mappingModel.setVersions(resource.lastModified());
mappingModel.setConfigFilePath(path); xmlStreams = resources.stream()
.map(xml -> {
try {
return xml.getInputStream();
} catch (IOException ioe) {
throw new ApplicationException(ioe);
}
})
.collect(Collectors.toList());
List<EasySearchMappingsDocument.EasySearchMappings> mappings = xmlStreams.stream().map(is -> {
try {
return EasySearchMappingsDocument.Factory.parse(is).getEasySearchMappings();
} catch (XmlException | IOException e) {
throw new ApplicationException(e);
}
}).collect(Collectors.toList());
EasySearchMappingModel mappingModel = new EasySearchMappingModel(mappings);
mappingModel.setVersions(maxLastModified(resources));
mappingModel.setConfigFilePaths(paths);
return mappingModel; return mappingModel;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw new ResourceLoadException(String.format("读取配置文件[%s]失败:%s", defaultPath, e.getMessage()));
throw new ResourceLoadException(String.format("读取配置文件[%s]失败:%s", path, e.getMessage()));
} finally { } finally {
if (inputStream != null) { xmlStreams.forEach(IOUtils::closeQuietly);
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
} }
} }
\ No newline at end of file
...@@ -4,10 +4,23 @@ import com.huigou.exception.ResourceLoadException; ...@@ -4,10 +4,23 @@ import com.huigou.exception.ResourceLoadException;
import com.huigou.uasp.bmp.common.easysearch.domain.model.EasySearchMappingModel; import com.huigou.uasp.bmp.common.easysearch.domain.model.EasySearchMappingModel;
public interface EasySearchLoadInterface { public interface EasySearchLoadInterface {
/**
* @since 1.1.3
*/
String XML_BASE_DIRECTORY = "config/content/easysearch";
/** /**
* 配置文件默认路径 * 配置文件默认路径
*/ */
public final static String XML_PATH = "config/content/easysearch/easy-search-%s.xml"; String XML_PATH = String.join("/", XML_BASE_DIRECTORY, "easy-search-%s.xml");
/**
* 方言配置文件路径
*
* @since 1.1.3
*/
String DIALECT_XML_PATH = String.join("/", XML_BASE_DIRECTORY, "%s", "easy-search-%s.xml");
public EasySearchMappingModel loadConfigFile(String path) throws ResourceLoadException; EasySearchMappingModel loadConfigFile(String path) throws ResourceLoadException;
} }
package com.huigou.uasp.bmp.common.easysearch.domain.model; package com.huigou.uasp.bmp.common.easysearch.domain.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.huigou.uasp.bmp.easysearch.EasySearchDocument.EasySearch; import com.huigou.uasp.bmp.easysearch.EasySearchDocument.EasySearch;
import com.huigou.uasp.bmp.easysearch.EasySearchMappingsDocument.EasySearchMappings; import com.huigou.uasp.bmp.easysearch.EasySearchMappingsDocument.EasySearchMappings;
import com.huigou.util.ConfigFileVersion; import com.huigou.util.ConfigFileVersion;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/** /**
* 快捷查询配置映射模型 * 快捷查询配置映射模型
* *
* @author Gerald * @author Gerald
*/ */
public class EasySearchMappingModel implements Serializable, ConfigFileVersion { public class EasySearchMappingModel implements Serializable, ConfigFileVersion {
private static final long serialVersionUID = 173704882069216812L; private static final long serialVersionUID = 173704882069216812L;
private Map<String, QuerySchemeModel> querySchemes;// 包含查询配置文件 /**
* 包含查询配置文件
*/
private final List<Map<String, QuerySchemeModel>> querySchemes;
private Long versions; private Long versions;
private String configFilePath; private List<String> configFilePaths;
/** /**
* 正则表达式去除空格,制表符及换行符 * 正则表达式去除空格,制表符及换行符
...@@ -31,19 +34,26 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion { ...@@ -31,19 +34,26 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion {
private static final Pattern pattern = Pattern.compile("\t|\r|\n"); private static final Pattern pattern = Pattern.compile("\t|\r|\n");
public EasySearchMappingModel(EasySearchMappings mappings) { public EasySearchMappingModel(EasySearchMappings mappings) {
querySchemes = new HashMap<String, QuerySchemeModel>(mappings.getEasySearchArray().length); this(Arrays.asList(mappings));
for (EasySearch easySearch : mappings.getEasySearchArray()) { }
querySchemes.put(easySearch.getName(), parseQueryScheme(easySearch));
} /**
* @since 1.1.3
*/
public EasySearchMappingModel(List<EasySearchMappings> mappings) {
querySchemes = mappings.stream()
.filter(Objects::nonNull)
.map(m -> Arrays.stream(m.getEasySearchArray()).collect(Collectors.toMap(EasySearch::getName, this::parseQueryScheme)))
.collect(Collectors.toList());
} }
/** /**
* 解析每个查询配置 * 解析每个查询配置
* *
* @Title: parseQueryScheme
* @author
* @param easySearch * @param easySearch
* @return QuerySchemeModel * @return QuerySchemeModel
* @Title: parseQueryScheme
* @author
*/ */
private QuerySchemeModel parseQueryScheme(EasySearch easySearch) { private QuerySchemeModel parseQueryScheme(EasySearch easySearch) {
QuerySchemeModel model = new QuerySchemeModel(easySearch.getFieldArray().length); QuerySchemeModel model = new QuerySchemeModel(easySearch.getFieldArray().length);
...@@ -69,7 +79,10 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion { ...@@ -69,7 +79,10 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion {
* 获取查询配置 * 获取查询配置
*/ */
public QuerySchemeModel getQuerySchemeModel(String name) { public QuerySchemeModel getQuerySchemeModel(String name) {
return querySchemes.get(name); return querySchemes.stream()
.map(queryScheme -> queryScheme.get(name))
.findFirst()
.get();
} }
@Override @Override
...@@ -81,13 +94,28 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion { ...@@ -81,13 +94,28 @@ public class EasySearchMappingModel implements Serializable, ConfigFileVersion {
this.versions = versions; this.versions = versions;
} }
/**
* @deprecated 已被 {@link #setConfigFilePaths(List)} 替代。
*/
@Deprecated
public void setConfigFilePath(String configFilePath) { public void setConfigFilePath(String configFilePath) {
this.configFilePath = configFilePath; this.configFilePaths = Collections.singletonList(configFilePath);
} }
@Override @Override
public String getFilePath() { public String getFilePath() {
return configFilePath; return configFilePaths.get(0);
} }
/**
* @since 1.1.3
*/
public void setConfigFilePaths(List<String> configFilePaths) {
this.configFilePaths = configFilePaths;
}
@Override
public List<String> getFilePaths() {
return configFilePaths;
}
} }
package com.huigou.uasp.bmp.common.treeview.domain.model; package com.huigou.uasp.bmp.common.treeview.domain.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.huigou.data.query.XMLParseUtil; import com.huigou.data.query.XMLParseUtil;
...@@ -15,12 +17,12 @@ import com.huigou.util.ConfigFileVersion; ...@@ -15,12 +17,12 @@ import com.huigou.util.ConfigFileVersion;
/** /**
* 树查询配置模型 * 树查询配置模型
* *
* @author
* @version V1.0
* @ClassName: TreeViewMappingModel * @ClassName: TreeViewMappingModel
* @Description: TODO * @Description: TODO
* @author
* @date 2014-3-11 上午09:58:04 * @date 2014-3-11 上午09:58:04
* @version V1.0
*/ */
public class TreeViewMappingModel implements Serializable, ConfigFileVersion { public class TreeViewMappingModel implements Serializable, ConfigFileVersion {
...@@ -30,10 +32,10 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion { ...@@ -30,10 +32,10 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion {
private Long version; private Long version;
private String configFilePath; private List<String> configFilePaths;
public TreeViewMappingModel(TreeMappings mapping) { public TreeViewMappingModel(TreeMappings mapping) {
trees = new HashMap<String, TreeModel>(mapping.getTreeArray().length); trees = new HashMap<>(mapping.getTreeArray().length);
for (Tree tree : mapping.getTreeArray()) { for (Tree tree : mapping.getTreeArray()) {
trees.put(tree.getName(), parseTreeModel(tree)); trees.put(tree.getName(), parseTreeModel(tree));
} }
...@@ -41,7 +43,7 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion { ...@@ -41,7 +43,7 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion {
/** /**
* 解析树模型 * 解析树模型
* *
* @param tree * @param tree
* @return * @return
*/ */
...@@ -82,12 +84,22 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion { ...@@ -82,12 +84,22 @@ public class TreeViewMappingModel implements Serializable, ConfigFileVersion {
this.version = version; this.version = version;
} }
@Override
public String getFilePath() { public String getFilePath() {
return configFilePath; return configFilePaths.get(0);
}
public void setConfigFilePaths(List<String> configFilePaths) {
this.configFilePaths = configFilePaths;
}
@Override
public List<String> getFilePaths() {
return configFilePaths;
} }
public void setConfigFilePath(String configFilePath) { public void setConfigFilePath(String configFilePath) {
this.configFilePath = configFilePath; this.configFilePaths = Collections.singletonList(configFilePath);
} }
} }
package com.huigou.uasp.bmp.intercept; package com.huigou.uasp.bmp.intercept;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import com.huigou.exception.ApplicationException;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
...@@ -12,7 +14,7 @@ import com.huigou.util.ResourceLoadManager; ...@@ -12,7 +14,7 @@ import com.huigou.util.ResourceLoadManager;
/** /**
* EhCache 缓存拦截器 * EhCache 缓存拦截器
* *
* @author xx * @author xx
*/ */
public class EhCacheInterceptor implements MethodInterceptor, InitializingBean { public class EhCacheInterceptor implements MethodInterceptor, InitializingBean {
...@@ -42,7 +44,7 @@ public class EhCacheInterceptor implements MethodInterceptor, InitializingBean { ...@@ -42,7 +44,7 @@ public class EhCacheInterceptor implements MethodInterceptor, InitializingBean {
icache.put(cacheKey, (Serializable) result); icache.put(cacheKey, (Serializable) result);
} else { } else {
ConfigFileVersion versions = (ConfigFileVersion) element; ConfigFileVersion versions = (ConfigFileVersion) element;
Long lastModified = ResourceLoadManager.getLastModified(versions.getFilePath()); long lastModified = ResourceLoadManager.maxLastModified(versions.getFilePaths());
if (lastModified > versions.getVersion()) { if (lastModified > versions.getVersion()) {
result = invocation.proceed(); result = invocation.proceed();
icache.put(cacheKey, (Serializable) result); icache.put(cacheKey, (Serializable) result);
...@@ -54,13 +56,10 @@ public class EhCacheInterceptor implements MethodInterceptor, InitializingBean { ...@@ -54,13 +56,10 @@ public class EhCacheInterceptor implements MethodInterceptor, InitializingBean {
/** /**
* 返回具体的方法全路径名称 参数 * 返回具体的方法全路径名称 参数
* *
* @param targetName * @param targetName 全路径
* 全路径 * @param methodName 方法名称
* @param methodName * @param arguments 参数
* 方法名称
* @param arguments
* 参数
* @return 完整方法名称 * @return 完整方法名称
*/ */
private String getCacheKey(String targetName, String methodName, Object[] arguments) { private String getCacheKey(String targetName, String methodName, Object[] arguments) {
......
...@@ -22,11 +22,6 @@ ...@@ -22,11 +22,6 @@
<property name="queryXmlManager" ref="queryXmlManager" /> <property name="queryXmlManager" ref="queryXmlManager" />
</bean> </bean>
<bean id="mapperScannerConfigurer" class="com.topsunit.query.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.huigou.**.mapper"/>
<property name="sqlExecutorBeanName" value="sqlExecutorDao" />
</bean>
<bean id="generalRepository" class="com.huigou.data.repository.GeneralRepository"> <bean id="generalRepository" class="com.huigou.data.repository.GeneralRepository">
</bean> </bean>
......
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
<property name="permissionBuilder" ref="queryPermissionBuilder"/> <property name="permissionBuilder" ref="queryPermissionBuilder"/>
</bean> </bean>
<!--快捷查询控件配置 --> <!--快捷查询控件配置 -->
<bean id="easySearchManager" class="com.huigou.uasp.bmp.common.easysearch.EasySearchManager"/> <bean id="easySearchManager" class="com.huigou.uasp.bmp.common.easysearch.EasySearchManager">
<property name="sqlDialect" value="${sqlDialect}"/>
</bean>
<bean id="easySearchApplication" <bean id="easySearchApplication"
class="com.huigou.uasp.bmp.common.easysearch.application.impl.EasySearchApplicationImpl"> class="com.huigou.uasp.bmp.common.easysearch.application.impl.EasySearchApplicationImpl">
<property name="sqlQuery" ref="sqlQuery"/> <property name="sqlQuery" ref="sqlQuery"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment