All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onetwo.dbm.utils.Dbms Maven / Gradle / Ivy

The newest version!
package org.onetwo.dbm.utils;

import java.io.Serializable;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;

import javax.sql.DataSource;

import org.apache.commons.lang3.tuple.Pair;
import org.onetwo.common.db.BaseCrudEntityManager;
import org.onetwo.common.db.spi.BaseEntityManager;
import org.onetwo.common.db.spi.CrudEntityManager;
import org.onetwo.common.ds.TransactionManagerAwareDataSource;
import org.onetwo.common.exception.BaseException;
import org.onetwo.common.spring.SpringUtils;
import org.onetwo.common.spring.Springs;
import org.onetwo.dbm.core.internal.DbmEntityManagerImpl;
import org.onetwo.dbm.core.internal.DbmSessionFactoryImpl;
import org.onetwo.dbm.core.internal.SimpleDbmInnerServiceRegistry;
import org.onetwo.dbm.core.internal.SimpleDbmInnerServiceRegistry.DbmServiceRegistryCreateContext;
import org.onetwo.dbm.core.spi.DbmSessionFactory;
import org.onetwo.dbm.core.spi.DbmSessionImplementor;
import org.onetwo.dbm.core.spi.DbmTransaction;
import org.onetwo.dbm.exception.DbmException;
import org.onetwo.dbm.spring.DbmEntityManagerCreateEvent;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionTimedOutException;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

/****
 * 如果需要使用多数据源,注意配置ChainedTransactionManager
 * @author way
 *
 */
final public class Dbms {
//	static final private Logger logger = JFishLoggerFactory.getLogger(Dbms.class);
	
	final private static LoadingCache, CrudEntityManager> CRUD_MANAGER_MAPPER = CacheBuilder.newBuilder()
																						.weakKeys()
																						.weakValues()
																						.build(new CacheLoader, CrudEntityManager>() {

																							@Override
																							public CrudEntityManager load(Class entityClass) throws Exception {
																								Pair beanDef = createCrudEntityManagerBeanBeanDefinition(entityClass);
																								CrudEntityManager crudManager = (CrudEntityManager)Springs.getInstance().getBean(beanDef.getLeft());
																								return crudManager;
																							}
																							
																						});
	
	final private static LoadingCache ENTITY_MANAGER_MAPPER = CacheBuilder.newBuilder()
																						.weakKeys()
																						.weakValues()
																						.build(new CacheLoader() {

																							@Override
																							public BaseEntityManager load(DataSource ds) throws Exception {
																								if(obtainBaseEntityManager().getSessionFactory().getDataSource().equals(ds)){
																									return obtainBaseEntityManager();
																								}
																								return newEntityManager(ds);
																							}
																							
																						});
	
	private static class BaseEntityManagerHoder {
		private static BaseEntityManager instance = Springs.getInstance().getBean(BaseEntityManager.class);
	}
	
	/***
	 * 获取默认的BaseEntityManager实例
	 * @return
	 */
	public static BaseEntityManager obtainBaseEntityManager(){
		return BaseEntityManagerHoder.instance;
	}
	
	/****
	 * 获取数据源对应的BaseEntityManager实例,dbm会根据传入的数据库创建一个BaseEntityManager实例
	 * @param dataSource
	 * @return
	 */
	public static BaseEntityManager obtainBaseEntityManager(DataSource dataSource) {
		try {
			return ENTITY_MANAGER_MAPPER.get(dataSource);
		} catch (ExecutionException e) {
			throw new BaseException("obtain BaseEntityManager error: " + e.getMessage(), e);
		}
	}
	/***
	 * 创建BaseEntityManager对象
	 * 注意BaseEntityManager对象都不包含事务拦截
	 * @param dataSource
	 * @return
	 */
	public static BaseEntityManager newEntityManager(DataSource dataSource) {
		DbmSessionFactory sf = newSessionFactory(dataSource);
		DbmEntityManagerImpl entityManager = new DbmEntityManagerImpl(sf);
		try {
//			entityManager.afterPropertiesSet();
			SpringUtils.injectAndInitialize(Springs.getInstance().getAppContext(), entityManager);
			DbmEntityManagerCreateEvent.publish(Springs.getInstance().getAppContext(), entityManager);
		} catch (Exception e) {
			throw new DbmException("init CrudEntityManager error: " +e.getMessage());
		}
		return entityManager;
	}
	
	@SuppressWarnings("unchecked")
	public static  CrudEntityManager obtainCrudManager(Class entityClass){
		try {
			return (CrudEntityManager)CRUD_MANAGER_MAPPER.get(entityClass);
		} catch (ExecutionException e) {
			throw new BaseException("obtain entityManager error: " + e.getMessage(), e);
		}
	}
	
	/****
	 * 使用spring配置的数据源创建CrudEntityManager
	 * 注意这样直接new创建的CrudEntityManager没有事务拦截,请在已配置事务的环境中使用
	 * @param entityClass
	 * @return
	 */
	public static  CrudEntityManager newCrudManager(Class entityClass){
		return new BaseCrudEntityManager<>(entityClass, null);
	}
	
	static Pair createCrudEntityManagerBeanBeanDefinition(Class entityClass){
		String beanName = CrudEntityManager.class.getSimpleName()+"-"+entityClass.getName();
		BeanDefinition beandef = BeanDefinitionBuilder.rootBeanDefinition(BaseCrudEntityManager.class)
				.addConstructorArgValue(entityClass)
				.addConstructorArgValue(null)
				.setScope(BeanDefinition.SCOPE_SINGLETON)
//				.setRole(BeanDefinition.ROLE_APPLICATION)
				.getBeanDefinition();
		BeanDefinitionRegistry registry = SpringUtils.getBeanDefinitionRegistry(Springs.getInstance().getAppContext());
		registry.registerBeanDefinition(beanName, beandef);
		return Pair.of(beanName, beandef);
	}
	/*****
	 * 使用指定的数据源创建CrudEntityManager
	 * 注意这样直接new创建的CrudEntityManager没有事务拦截,请在已配置事务的环境中使用
	 * @param entityClass
	 * @param dataSource
	 * @return
	 */
	public static  CrudEntityManager newCrudManager(Class entityClass, DataSource dataSource){
		return new BaseCrudEntityManager<>(entityClass, newEntityManager(dataSource));
	}
	public static  CrudEntityManager newCrudManager(Class entityClass, BaseEntityManager baseEntityManager){
		return new BaseCrudEntityManager<>(entityClass, baseEntityManager);
	}
	
	
	public static DbmSessionFactory newSessionFactory(DataSource dataSource){
		ApplicationContext appContext = Springs.getInstance().getAppContext();
		DbmSessionFactoryImpl sf = null;
		if (dataSource instanceof TransactionManagerAwareDataSource) {
			TransactionManagerAwareDataSource ds = (TransactionManagerAwareDataSource) dataSource;
			sf = new DbmSessionFactoryImpl(appContext, ds.getTransactionManager(), dataSource);
		} else {
			sf = new DbmSessionFactoryImpl(appContext, null, dataSource);
		}
		sf.setServiceRegistry(SimpleDbmInnerServiceRegistry.obtainServiceRegistry(new DbmServiceRegistryCreateContext(appContext, sf)));
		sf.afterPropertiesSet();
		return sf;
	}
	

	public static  R doInRequiresNewPropagation(BaseEntityManager baseEntityManager, Function func) {
		return doInPropagation(baseEntityManager.getSessionFactory(), TransactionDefinition.PROPAGATION_REQUIRES_NEW, func);
	}
	
	public static  R doInPropagation(DbmSessionFactory sf, int propagationBehavior, Function func) {
		return doInPropagation(sf, propagationBehavior, TransactionDefinition.TIMEOUT_DEFAULT, func);
	}
	
	/****
	 * 
	 * @author weishao zeng
	 * @param sf
	 * @param propagationBehavior
	 * @param timeoutInSeconds 事务超时时间,这个超时是非中断式触发的,只是每次执行的时候由 ResourceHolderSupport#checkTransactionTimeout 触发检查
	 * @param func
	 * @return
	 */
	public static  R doInPropagation(DbmSessionFactory sf, int propagationBehavior, int timeoutInSeconds, Function func) {
		DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
		definition.setPropagationBehavior(propagationBehavior);
		definition.setTimeout(timeoutInSeconds);
		return doInPropagation(sf, definition, func);
	}
	
	public static  R doInPropagation(DbmSessionFactory sf, TransactionDefinition definition, Function func) {
		DbmSessionImplementor session = (DbmSessionImplementor)sf.openSession();
		DbmTransaction transaction = session.beginTransaction(definition);
		try {
			R result = func.apply(transaction);
			transaction.commit();
			return result;
		} catch (TransactionTimedOutException e) {
			transaction.rollback();
			throw e;
		}  catch (DbmException e) {
			transaction.rollback();
			throw e;
		} catch (Exception e) {
			transaction.rollback();
			throw new DbmException("doInRequiresNewPropagation error", e);
		} 
	}
	
	private Dbms(){
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy