org.onetwo.dbm.utils.DbmUtils Maven / Gradle / Ivy
package org.onetwo.dbm.utils;
import java.lang.annotation.Annotation;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.onetwo.common.date.DateUtils;
import org.onetwo.common.db.dquery.condition.directive.DynamicConditionDirective;
import org.onetwo.common.db.filequery.directive.SetDirective;
import org.onetwo.common.db.filequery.directive.WhereDirective;
import org.onetwo.common.log.JFishLoggerFactory;
import org.onetwo.common.reflect.ReflectUtils;
import org.onetwo.common.spring.SpringUtils;
import org.onetwo.common.spring.Springs;
import org.onetwo.common.spring.ftl.AbstractFreemarkerTemplateConfigurer;
import org.onetwo.common.spring.ftl.DateRangeDirective;
import org.onetwo.common.spring.ftl.ForeachDirective;
import org.onetwo.common.spring.ftl.StrDirective;
import org.onetwo.common.utils.CUtils;
import org.onetwo.common.utils.LangUtils;
import org.onetwo.dbm.annotation.DbmFieldListeners;
import org.onetwo.dbm.core.spi.DbmTransaction;
import org.onetwo.dbm.exception.DbmException;
import org.onetwo.dbm.exception.UpdateCountException;
import org.onetwo.dbm.jdbc.JdbcUtils;
import org.onetwo.dbm.jdbc.method.JdbcOperationMethod;
import org.onetwo.dbm.jdbc.spi.SqlParametersProvider;
import org.onetwo.dbm.mapping.DbmEntityFieldListener;
import org.onetwo.dbm.mapping.DbmEnumValueMapping;
import org.onetwo.dbm.mapping.DbmMappedField;
import org.onetwo.dbm.spring.EnableDbm;
import org.slf4j.Logger;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.jdbc.core.SqlProvider;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
final public class DbmUtils {
private static final Logger logger = JFishLoggerFactory.getLogger(DbmUtils.class);
public static final int MAX_PRINTABLE_ARG_SIZE = 50;
public final static ConversionService CONVERSION_SERVICE = new DefaultConversionService();
private static final String CHAINED_TRANSACTION_MANAGER = "org.springframework.data.transaction.ChainedTransactionManager";
public static final int INVALID_VALUE_FIRST_RECORD = -1;
public static final int INVALID_VALUE_MAX_RESULTS = 0;
public static final String FIRST_RESULT_NAME = "DbmQueryFirstResult";
public static final String MAX_RESULT_NAME = "DbmQueryMaxResult";
/****
* 是否分页
* @author weishao zeng
* @param first
* @param maxResults
* @return
*/
public static boolean isLimitedQuery(Integer first, Integer maxResults){
return first>INVALID_VALUE_FIRST_RECORD && maxResults>INVALID_VALUE_MAX_RESULTS;
}
public static boolean isChanedTransactionManagerPresent(){
return ClassUtils.isPresent(CHAINED_TRANSACTION_MANAGER, ClassUtils.getDefaultClassLoader());
}
public static void throwIfEffectiveCountError(String errorMsg, int expectCount, int effectiveCount){
if(effectiveCount!=expectCount)
throw new UpdateCountException(errorMsg, expectCount, effectiveCount);
}
public static List initDbmEntityFieldListeners(DbmFieldListeners listenersAnntation){
Assert.notNull(listenersAnntation, "listenersAnntationn can not be null");
Class extends DbmEntityFieldListener>[] flClasses = listenersAnntation.value();
List fieldListeners = Lists.newArrayList();
for(Class extends DbmEntityFieldListener> flClass : flClasses){
DbmEntityFieldListener fl = DbmUtils.createDbmBean(flClass); // ReflectUtils.newInstance(flClass);
fieldListeners.add(fl);
}
return fieldListeners;
}
/*public static Object getActualSqlValue(Object value){
if(value!=null && Enum.class.isAssignableFrom(value.getClass())){
// return Types.asValue(value.toString(), value.getClass());
return ((Enum>)value).name();
}
return value;
}*/
public static Map lookupColumnNames(SqlRowSetMetaData resultSetMetaData) throws SQLException {
int columnCount = resultSetMetaData.getColumnCount();
Map names = new HashMap();
for (int index = 1; index <= columnCount; index++) {
String columName = lookupColumnName(resultSetMetaData, index);
names.put(JdbcUtils.lowerCaseName(columName), index);
names.put(columName, index);
}
return names;
}
public static String lookupColumnName(SqlRowSetMetaData resultSetMetaData, int columnIndex) throws SQLException {
String name = resultSetMetaData.getColumnLabel(columnIndex);
if (name == null || name.length() < 1) {
name = resultSetMetaData.getColumnName(columnIndex);
}
return name;
}
public static Collection getAllDbmPackageNames(ApplicationContext applicationContext){
ListableBeanFactory bf = (ListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
return getAllDbmPackageNames(bf);
}
public static Collection getAllDbmPackageNames(ListableBeanFactory beanFactory){
Collection packageNames = new HashSet<>();
packageNames.addAll(scanEnableDbmPackages(beanFactory));
// packageNames.addAll(scanDbmPackages(beanFactory));
return packageNames;
}
public static List scanEnableDbmPackages(ApplicationContext applicationContext){
ListableBeanFactory bf = (ListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
return scanEnableDbmPackages(bf);
}
/***
* 首先找到标注了 annotationCLass 注解(比如 @EnableDbm )的bean
* 然后读取注解的packagesToScan属性值,有则返回此值
* 没有则返回标注了注解的bean所在包,作为返回值
*
* sample:
*
* @EnableDbm
* class EnableDbmBean {
* }
*
* Set packageNames = SpringAnnotationUtils.scanAnnotationPackages(applicationContext, EnableDbmBean.class)
* packageNames = EnableDbmUIBean.class.getPackage().getName();
*
* @author weishao zeng
* @param beanFactory
* @return
*/
public static List scanEnableDbmPackages(ListableBeanFactory beanFactory){
List packageNames = new ArrayList();
SpringUtils.scanAnnotation(beanFactory, EnableDbm.class, (beanDef, beanClass)->{
EnableDbm enableDbm = beanClass.getAnnotation(EnableDbm.class);
if(enableDbm==null){
return ;
}
String[] modelPacks = enableDbm.packagesToScan();
if(ArrayUtils.isNotEmpty(modelPacks)){
for(String pack : modelPacks){
packageNames.add(pack);
}
}else{
String packageName = beanClass.getPackage().getName();
if(!packageName.startsWith("org.onetwo.")){
packageNames.add(packageName);
}
}
});
return packageNames;
}
/*public static List scanDbmPackages(ApplicationContext applicationContext){
ListableBeanFactory bf = (ListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
return scanDbmPackages(bf);
}
public static List scanDbmPackages(ListableBeanFactory beanFactory){
return scanAnnotationPackages(beanFactory, DbmPackages.class, dbmPackages->dbmPackages.value());
}*/
public static List scanAnnotationPackages(ListableBeanFactory beanFactory,
Class annoClass,
Function packageExtractor){
List packageNames = new ArrayList();
SpringUtils.scanAnnotation(beanFactory, annoClass, (beanDef, beanClass)->{
T annoInst = beanClass.getAnnotation(annoClass);
if(annoInst==null){
return ;
}
String[] modelPacks = packageExtractor.apply(annoInst);
if(ArrayUtils.isNotEmpty(modelPacks)){
for(String pack : modelPacks){
packageNames.add(pack);
}
}else{
String packageName = beanClass.getPackage().getName();
packageNames.add(packageName);
}
});
return packageNames;
}
public static void rollbackOnException(DbmTransaction transaction, Throwable ex) throws TransactionException {
logger.debug("Initiating transaction rollback on application exception", ex);
try {
transaction.rollback();
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
}
/*****
* find the {@link PlatformTransactionManager} from {@link ApplicationContext} by {@link DataSource}
* @param applicationContext
* @param dataSource
* @return
*/
public static PlatformTransactionManager getDataSourceTransactionManager(ApplicationContext applicationContext, DataSource dataSource, Supplier notFoudCallback){
if(DbmUtils.isChanedTransactionManagerPresent()){
List chaineds = SpringUtils.getBeans(applicationContext, ChainedTransactionManager.class);
for(ChainedTransactionManager chain : chaineds){
if(isChanedTMContainDataSource(chain, dataSource)){
return chain;
}
}
}
Map tms = SpringUtils.getBeansAsMap(applicationContext, DataSourceTransactionManager.class);
Entry tm = null;
for(Entry entry : tms.entrySet()){
if(isSameDataSource(entry.getValue(), dataSource)){
tm = entry;
break;
}
}
if(tm!=null){
if(logger.isDebugEnabled()){
logger.debug("auto find DataSourceTransactionManager for current dataSource: {}", tm.getKey());
}
return tm.getValue();
}else{
if(notFoudCallback!=null){
return notFoudCallback.get();
}
throw new DbmException("no DataSourceTransactionManager configurate for dataSource: " + dataSource);
}
}
public static boolean isSameDataSource(DataSourceTransactionManager tm, DataSource dataSource){
return tm.getDataSource().equals(dataSource);
}
@SuppressWarnings("unchecked")
public static boolean isChanedTMContainDataSource(ChainedTransactionManager chained, DataSource dataSource){
List lists = (List)ReflectUtils.getFieldValue(chained, "transactionManagers");
if(LangUtils.isEmpty(lists)){
return false;
}
for(PlatformTransactionManager tm : lists){
if(!DataSourceTransactionManager.class.isInstance(tm)){
continue;
}
DataSourceTransactionManager dtm = (DataSourceTransactionManager)tm;
if(isSameDataSource(dtm, dataSource)){
return true;
}
}
return false;
}
public static Pair findSqlAndParams(JdbcOperationMethod invokeMethod, Object[] args){
String sql;
Object sqlArgs = null;
if (invokeMethod.getSqlParameter()!=null) {
sql = (String)args[invokeMethod.getSqlParameter().getParameterIndex()];
if (invokeMethod.getSqlArgsParameter()!=null) {
sqlArgs = args[invokeMethod.getSqlArgsParameter().getParameterIndex()];
}
} else if (invokeMethod.getSqlProviderParameter()!=null) {
SqlProvider sqlProvider = (SqlProvider) args[invokeMethod.getSqlProviderParameter().getParameterIndex()];
sql = sqlProvider.getSql();
if (sqlProvider instanceof SqlParametersProvider) {
sqlArgs = ((SqlParametersProvider)sqlProvider).getSqlParameters();
}
} else {
throw new DbmException("sql parameter not found: " + invokeMethod.getMethod().getName());
}
Pair sqlParams = Pair.of(sql, sqlArgs);
return sqlParams;
}
public static Pair findSqlAndParams(Object[] args){
String sql = null;
Object params = null;
// int maxArgSize = 50;
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if(arg==null){
continue;
}
if(arg instanceof String){
sql = (String)arg;
}else if(arg instanceof Date){
params = DateUtils.formatDateTimeMillis((Date)arg);
}else if(arg instanceof Map){
params = arg;
}else if(arg.getClass().isArray()){
params = CUtils.tolist(arg, false);
}else if(arg instanceof Collection){//batch operation...
params = arg;
}else{
//if arg is SimpleArgsPreparedStatementCreator
if(arg instanceof SqlProvider){
sql = ((SqlProvider)arg).getSql();
}
if(arg instanceof SqlParametersProvider){
params = ((SqlParametersProvider)arg).getSqlParameterList();
}
}
// if (LangUtils.size(params)>maxArgSize) {
// params = "<>";
// }
}
if(sql==null){
return null;
}
return Pair.of(sql, params);
}
public static String objectToString(Object obj){
if (obj!=null && obj.getClass().isArray()) {
Object[] rawArgs = (Object[]) obj;
Object[] args = new Object[rawArgs.length];
for (int i = 0; i < rawArgs.length; i++) {
if (LangUtils.isMultiple(rawArgs[i]) && LangUtils.size(rawArgs[i]) > MAX_PRINTABLE_ARG_SIZE) {
args[i] = "<>";
} else {
args[i] = rawArgs[i];
}
}
return LangUtils.toString(args);
} else {
return LangUtils.toString(obj);
}
}
@SuppressWarnings("unchecked")
public static Object formatContainerValueIfNeed(Object arg) {
if (arg instanceof Map) {
Map, ?> temp = (Map, ?>) arg;
Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy