gu.sql2java.Managers Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-manager Show documentation
Show all versions of sql2java-manager Show documentation
sql2java manager class package for accessing database
package gu.sql2java;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static gu.sql2java.SimpleLog.log;
import static gu.sql2java.SimpleLog.logString;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import gu.sql2java.Constant.JdbcProperty;
/**
* 数据库操作实例({@link TableManager})管理类
* @author guyadong
*
*/
public class Managers implements Constant{
/**
* 设置是否输出调试信息标志
*/
private static boolean debug = false;
private Managers() {
}
private static final ImmutableMap>
tableManagerInstances = loadTableManager();
private static final ImmutableMap, TableManager extends BaseBean>>
tableManagerTypeMaps = asTypeMap(tableManagerInstances);
private static final ImmutableMap, TableManager extends BaseBean>>
tableManagerBeanTypeMaps = asBeanTypeMap(tableManagerInstances);
private static final Map, TableManager extends BaseBean>> cacheManagers = Maps.newHashMap();
private static final Map, TableManager extends BaseBean>> cacheBeanTypeManagers = Maps.newHashMap();
private static final Map> cacheNameManagers = Maps.newHashMap();
/**
* @return 返回所有数据库操作实例(非cache)
*/
public static ImmutableMap> getTableManagers() {
return tableManagerInstances;
}
/**
* SPI(Service Provider Interface)机制加载 {@link TableManager}所有实例
* @return 表名和 {@link TableManager}实例的映射对象
*/
private static ImmutableMap> loadTableManager() {
ImmutableMap.Builder> builder = ImmutableMap.builder();
for(RowMetaData data:RowMetaData.tableMetadata.values()){
try {
TableManager> manager = TableManagerDecorator.makeInterfaceInstance(new BaseTableManager<>(data.tablename));
builder.put(data.tablename, manager);
if(debug){
log("TableManagerDecorator instance create for {} ",data.tablename);
}
} catch (RuntimeException e) {
if(debug){
log("FAIL TO create manager for {} caused by {}",data.tablename,e.getMessage());
}
}
}
return builder.build();
}
private static final ImmutableMap, TableManager extends BaseBean>> asTypeMap(Map>input){
return Maps.uniqueIndex(input.values(), new Function,Class>>(){
@Override
public Class> apply(TableManager extends BaseBean> input) {
for(Class> clazz:input.getClass().getInterfaces()){
if(TableManager.class.isAssignableFrom(clazz)) {
return clazz;
}
}
throw new IllegalStateException(logString("NOT FOUND immplements interface class for %s ", input.getClass()));
}});
}
private static final ImmutableMap, TableManager extends BaseBean>> asBeanTypeMap(Map>input){
return Maps.uniqueIndex(input.values(), new Function,Class>>(){
@Override
public Class> apply(TableManager extends BaseBean> input) {
if(input instanceof BaseTableManager){
return ((BaseTableManager>)input).metaData.beanType;
}else if(Proxy.isProxyClass(input.getClass())){
InvocationHandler handler = Proxy.getInvocationHandler(input);
checkArgument(handler instanceof TableManagerDecorator,"UNKNOW HANDLER %s",handler.getClass() );
return ((TableManagerDecorator>)handler).metaData.beanType;
}
throw new IllegalArgumentException(logString("UNKNOW SUPPORTED TableManager instance %s",input.getClass()));
}});
}
/**
* 根据表操作接口类型返回数据库操作实例(非cache)
* @param interfaceClass 接口类型
* @return {@link TableManager}实例,找不到则抛出异常
*/
@SuppressWarnings("unchecked")
public static final >M
getTableManager(ClassinterfaceClass) {
TableManager extends BaseBean> manager = tableManagerTypeMaps.get(interfaceClass);
return checkNotNull((M) manager,"INVALID manager type %s",interfaceClass);
}
/**
* 根据表记录类型返回数据库操作实例(非cache)
* @param beanType java bean type
* @return {@link TableManager}实例,找不到则抛出异常
*/
@SuppressWarnings("unchecked")
public static final >M
getTableManagerByBeanType(ClassbeanType) {
TableManager extends BaseBean> manager = tableManagerBeanTypeMaps.get(beanType);
return checkNotNull((M) manager,"INVALID bean type %s",beanType);
}
/**
* 根据表名返回数据库操作实例(非cache)
* @param tablename table name
* @return {@link TableManager}实例,找不到则抛出异常
*/
@SuppressWarnings("unchecked")
public static final >M
getTableManager(String tablename) {
TableManager extends BaseBean> manager = tableManagerInstances.get(tablename);
return checkNotNull((M) manager,"INVALID tablename %s",tablename);
}
/**
* 根据表名返回数据库操作实例(非cache)
* @param tablename table name
* @return {@link BaseTableManager}实例,找不到则抛出异常
*/
@SuppressWarnings("unchecked")
public static final >M
getBaseTableManager(String tablename) {
return (M) baseManagerOf((TableManager>)getTableManager(tablename));
}
/**
* 注册cache manager
* @param tablename table name
* @param updateStrategy cache update strategy,{@link gu.sql2java.Constant#DEFAULT_STRATEGY} be used if {@code null}
* @param maximumSize maximum capacity of cache ,{@link gu.sql2java.Constant#DEFAULT_CACHE_MAXIMUMSIZE } be used if {@code null} or <=0,see also {@link com.google.common.cache.CacheBuilder#maximumSize(long)}
* @param duration cache data expired time,{@link gu.sql2java.Constant#DEFAULT_DURATION} be used if {@code null} or <=0,see also {@link com.google.common.cache.CacheBuilder#expireAfterAccess(long, TimeUnit)}
* @param unit time unit for {@code duration},{@link gu.sql2java.Constant#DEFAULT_TIME_UNIT} be used if {@code null},see also {@link com.google.common.cache.CacheBuilder#expireAfterAccess(long, TimeUnit)}
*/
public static synchronized final >
void registerCacheManager(
String tablename,
UpdateStrategy updateStrategy,
long maximumSize,
long duration,
TimeUnit unit){
TableManager> cacheManager = CacheManager.makeCacheInstance(tablename, updateStrategy, maximumSize, duration, unit);
BaseTableManager> manager = baseManagerOf(cacheManager);
cacheManagers.put(manager.metaData.managerInterfaceClass, cacheManager);
cacheNameManagers.put(manager.metaData.tablename, cacheManager);
cacheBeanTypeManagers.put(manager.metaData.beanType, cacheManager);
if(debug){
log("REGISTER CACHE MANAGER {}",cacheManager);
}
}
/**
* @return 返回所有支持缓存的数据库操作实例
* @see CacheManager
*/
public static Map, TableManager extends BaseBean>> getCacheManagers() {
return Collections.unmodifiableMap(cacheManagers);
}
/**
* 根据目标类型返回对应的支持缓存的 {@link TableManager}实例
* @param interfaceClass 目标接口类型
* @return {@link TableManager}实例
* @throws NoSuchElementException 找不到时抛出异常
*/
@SuppressWarnings("unchecked")
public static final >M
getCacheManager(final ClassinterfaceClass) throws NoSuchElementException {
checkArgument(interfaceClass != null,"targetType is null");
TableManager extends BaseBean> manager;
if(null != (manager = cacheManagers.get(interfaceClass))){
return (M) manager;
}
return (M) Iterables.find(cacheManagers.values(), new Predicate>() {
@Override
public boolean apply(TableManager> input) {
return interfaceClass.isInstance(input);
}
});
}
/**
* 根据表记录类型返回支持缓存的数据库操作实例
* @param beanType java bean type
* @return {@link TableManager}实例,找不到时抛出异常
*/
@SuppressWarnings("unchecked")
public static final TableManager
getCacheManagerByBeanType(Class> beanType) {
TableManager extends BaseBean> manager = cacheBeanTypeManagers.get(beanType);
return ( TableManager) checkNotNull(manager,"INVALID bean type %s",beanType);
}
/**
* 根据表名返回支持缓存的数据库操作实例
* @param tablename
* @return {@link TableManager}实例,找不到时抛出异常
*/
@SuppressWarnings("unchecked")
public static final TableManager
getCacheManager(String tablename) {
TableManager extends BaseBean> manager = cacheNameManagers.get(tablename);
return (TableManager) checkNotNull(manager,"INVALID table name %s",tablename);
}
/**
* 根据表记录类型返回支持缓存的数据库操作实例
* @param beanType java bean type
* @return {@link CacheManager}实例,找不到时返回{@code null}
* @since 3.30.0
*/
@SuppressWarnings({ "rawtypes" })
public static final CacheManager
getCacheManagerByBeanTypeOrNull(Class> beanType) {
TableManager extends BaseBean> manager = cacheBeanTypeManagers.get(beanType);
if(null != manager) {
TableManagerDecorator handler = (TableManagerDecorator) Proxy.getInvocationHandler(manager);
return (CacheManager) handler.delegate;
}
return null;
}
/**
* 根据表名返回支持缓存的数据库操作实例
* @param tablename
* @return {@link CacheManager}实例,找不到时返回{@code null}
* @since 3.30.0
*/
@SuppressWarnings({ "rawtypes" })
public static final CacheManager
getCacheManagerOrNull(String tablename) {
TableManager extends BaseBean> manager = cacheNameManagers.get(tablename);
if(null != manager) {
TableManagerDecorator handler = (TableManagerDecorator) Proxy.getInvocationHandler(manager);
return (CacheManager) handler.delegate;
}
return null;
}
/**
* 根据表记录类型返回数据库操作实例
* 优先返回支持缓存的数据库操作实例(cache)
* @param interfaceClass 接口类
* @return {@link TableManager}实例,找不到时抛出异常
*/
public static >M
instanceOf(ClassinterfaceClass) {
try {
return getCacheManager(interfaceClass);
} catch (Exception e) {
return getTableManager(interfaceClass);
}
}
/**
* 根据表名返回数据库操作实例
* 优先返回支持缓存的数据库操作实例(cache)
* @param tablename table name
* @return {@link TableManager}实例,找不到时抛出异常
*/
public static TableManager managerOf(String tablename) {
try {
return getCacheManager(tablename);
} catch (Exception e) {
return getTableManager(tablename);
}
}
/**
* 将数据库操作实例转换对应的{@link BaseTableManager}实例
* @param manager
* @return {@link BaseTableManager}实例,转换失败时抛出异常
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
static BaseTableManager baseManagerOf(TableManager manager){
checkArgument(manager != null,"manager is null");
if(manager instanceof BaseTableManager){
return (BaseTableManager) manager;
}else if(Proxy.isProxyClass(manager.getClass())){
InvocationHandler handler = Proxy.getInvocationHandler(manager);
checkArgument(handler instanceof TableManagerDecorator,"UNKNOW HANDLER TYPE %s",manager.getClass());
return ((TableManagerDecorator)handler).delegate;
}else {
throw new IllegalArgumentException(logString("UNKNOW TableManager instance type %s",manager.getClass()));
}
}
/**
* 从数据库操作接口类获取对应的{@link BaseTableManager}实例
* @param interfaceClass
* @return {@link BaseTableManager}实例,转换失败时抛出异常
*/
static >BaseTableManager baseManagerOf(Class interfaceClass){
return baseManagerOf(instanceOf(interfaceClass));
}
/**
* 根据表名返回对应的{@link BaseTableManager}实例
* 优先返回支持缓存的数据库操作实例(cache)
* @param tablename table name
* @return {@link BaseTableManager}实例,找不到时抛出异常
*/
@SuppressWarnings("unchecked")
static BaseTableManager baseManagerOf(String tablename) {
return baseManagerOf((TableManager)managerOf(tablename));
}
/**
* 根据数据表名(驼峰命名格式)返回对应的{@link TableManager}实例
* 优先返回支持缓存的数据库操作实例(cache)
* @param coreClass
* @param alias 别名
* @return {@link TableManager}实例,找不到时抛出异常
* @deprecated never used
*/
public static TableManager managerOfCoreClass(String coreClass, String alias) {
String tablename = RowMetaData.getRowMetaDataByCoreClassName(coreClass, alias).tablename;
try {
return getCacheManager(tablename);
} catch (Exception e) {
return getTableManager(tablename);
}
}
/**
* 根据表记录类型返回数据库操作实例
* 优先返回支持缓存的数据库操作实例
* @param beanType java bean type
* @return {@link TableManager}实例,找不到时抛出异常
*/
public static TableManager managerOf(Class beanType) {
try {
return getCacheManagerByBeanType(beanType);
} catch (Exception e) {
return getTableManagerByBeanType(beanType);
}
}
public enum Module{
MANAGER,CACHE,DECORATOR,MANAGERS,BASETABLEMANAGER
}
/**
* set debug flag that determine if output log message,default : false
* @param debug flag for debug message output
* @param modules modules array to be set debug flag,all modules used if be null or empty
*/
public static void setDebug(boolean debug,Module... modules){
if(modules == null || modules.length == 0){
modules = Module.values();
}
for(Module module:modules){
if(null != module){
switch (module) {
case MANAGER:
DataSourceConfig.setDebugOutput(debug);
break;
case CACHE:
ColumnCache.setDebug(debug);
break;
case DECORATOR:
TableManagerDecorator.setDebug(debug);
break;
case MANAGERS:
Managers.debug = debug;
break;
case BASETABLEMANAGER:
BaseTableManager.setDebug(debug);
break;
default:
break;
}
}
}
}
/**
* set flags for check if WHRE SQL is legal
* @param whereCheckFlag
*/
public static void setWhereCheckFlag(int whereCheckFlag) {
BaseTableManager.setWhereCheckFlag(whereCheckFlag);
}
/**
* set debug flag that determine if output log message for Manager instance named {@code alias},default : false
* @param alias alias name
* @param debug debug flag
* @deprecated
*/
public static void setDebugOfManager(String alias,boolean debug){
// DO NOTHING
}
/**
* 对所有{@link JdbcProperty}定义的属性如果值不为String则删除
* @param properties
* @return always properties
*/
@SuppressWarnings({ "rawtypes"})
private static Map cleanNotString(Map properties){
if(null != properties){
for(JdbcProperty property : JdbcProperty.values()){
if(!(properties.get(property.key) instanceof String)){
properties.remove(property.key);
}
if(!property.isGlobal()){
String key = property.withPrefix("debug.");
if(!(properties.get(key) instanceof String)){
properties.remove(key);
}
key = property.withPrefix("work.");
if(!(properties.get(key) instanceof String)){
properties.remove(key);
}
}
}
}
return properties;
}
/**
* 对配置参数进行归一化处理
* 对于{@link JdbcProperty}定义的所有属性进行归一化处理,如果有带'work.','debug.'前缀的属性,则优先使用,
* 如果有不带前缀的属性,则将属性名根据'debug'标志改为'work.'或'debug.'前缀的属性
* 比如: 如果同时存在jdbc.url, work.jdbc.url这两个定义,且debug标志为false(未定义时默认为false),则删除jdbc.url定义
* 如果只存在jdbc.url定义,且debug标志为false(未定义时默认为false),则将之改为work.jdbc.url
* @param properties
* @return new Map instance
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
static final Map normailze(Map properties){
HashMap m = new HashMap(properties);
if(null != properties){
cleanNotString(m);
if(!m.containsKey(JdbcProperty.DEBUG.key)){
m.put(JdbcProperty.DEBUG.key, "false");
}
boolean isDebug = Boolean.valueOf((String) m.get(JdbcProperty.DEBUG.key));
String prefix = isDebug?"debug.":"work.";
for(JdbcProperty property : JdbcProperty.values()){
// 跳过所有全局属性
if(!property.isGlobal()){
if(m.containsKey(property.key)){
Object value = m.remove(property.key);
if(!m.containsKey(property.withPrefix(prefix))){
// 有前缀的属性未定义时使用无前缀的属性代替
m.put(property.withPrefix(prefix), value);
}else{
// 有前缀的属性优先
}
}
}
}
}
return m;
}
/**
* inject properties to {@link DataSourceConfig#databaseProperties}
* be effected only while called before initializing singleton instance
* @param properties
* @param prefix the prefix of properties,ignore if {@code null}
* @see JdbcProperty
*/
@SuppressWarnings("rawtypes")
public static final void injectProperties(Map properties, String prefix){
DataSourceConfig.injectProperties(DataSourceConfig.asEnumMap(properties, prefix));
}
/**
* short cut of {@link #injectProperties(Map, String)}
*/
@SuppressWarnings("rawtypes")
public static final void injectProperties(Map properties){
injectProperties(properties, null);
}
/**
* @return singleton instance of {@link Manager} as {@link SqlRunner} instance
*/
public static SqlRunner getSqlRunner(){
return Manager.getInstance();
}
/**
* @param alias alias name of connection
* @return singleton instance of {@link Manager} as {@link SqlRunner} instance for alias
*/
public static SqlRunner getSqlRunner(String alias){
Manager manager = managerInstanceOfAlias(alias);
return manager == null ? getSqlRunner() : manager;
}
/**
* get Manager instance with jdbcUrl
* @param jdbcUrl JDBC connect string
* @return Manager instance OR null if not found
*/
public static Manager managerInstanceOf(String jdbcUrl){
return null == jdbcUrl ? null : Manager.managers.get(jdbcUrl);
}
/**
* get Manager instance with alias
* @param alias alias name of JDBC connection
* @return Manager instance OR null if not found
*/
public static Manager managerInstanceOfAlias(String alias){
if(Strings.isNullOrEmpty(alias)){
alias = DEFAULT_ALIAS;
}
return Manager.aliasManagers.get(alias);
}
/**
* create Manager instance with properties
* @param properties
* @return Manager instance
*/
@SuppressWarnings({ "rawtypes" })
public static synchronized Manager createInstance(Map properties){
properties = normailze(checkNotNull(properties, "properties is null"));
String alias = DataSourceConfig.parseValue(properties, JdbcProperty.ALIAS);
Manager manager = null;
if(!Strings.isNullOrEmpty(alias)){
manager = managerInstanceOfAlias(alias);
if( null != manager){
return manager;
}else{
DataSourceConfig config = DataSourceConfig.createConfig(asProperties(properties));
return new Manager(config);
}
}
String jdbcUrl = checkNotNull(DataSourceConfig.parseValue(properties, JdbcProperty.JDBC_URL),
"JDBC connect string is not defined");
manager = managerInstanceOf(jdbcUrl);
if(manager == null){
manager = new Manager(asProperties(properties));
}
return manager;
}
public static Manager createInstance(EnumMap properties){
return createInstance(asProperties(properties));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static Properties asProperties(Map properties){
if(properties instanceof Properties){
return (Properties)properties;
}
Properties props = new Properties();
if(null != properties){
props.putAll(properties);
}
return props;
}
/**
* convert {@link EnumMap } properties to {@link Properties}
* @param input input properties
*/
private static final Properties asProperties(EnumMap input){
Properties properties = new Properties();
DataSourceConfig.injectToProperties(properties, input);
return properties;
}
}