hibernate动态多数据源

Posted 姚__

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate动态多数据源相关的知识,希望对你有一定的参考价值。

hibernate动态多数据源包括自动建表

网上搜了不少,只有多数据源的配置,但最主要的自动建表没有,我研究清楚记录下

hibernate 动态多数据源配置

hibernate的xml配置文件,设置多个数据源

<bean id="dataSourceOne" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
	     <property name="url" value="${hibernate.connection.url}" />
	     <property name="username"><value>${hibernate.connection.username}</value></property>
	     <property name="password" value="${hibernate.connection.password}" />
	     <property name="filters"><value>stat</value></property>
	     <property name="maxActive"><value>100</value></property>
	     <property name="initialSize"><value>1</value></property>
	     <property name="maxWait"><value>60000</value></property>
	     <property name="minIdle"><value>1</value></property>
	     <property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
	     <property name="minEvictableIdleTimeMillis"><value>300000</value></property>
	     <property name="validationQuery"><value>SELECT 'x'</value></property>
	     <property name="testWhileIdle"><value>true</value></property>
	     <property name="testOnBorrow"><value>false</value></property>
	     <property name="testOnReturn"><value>false</value></property>

	     <property name="poolPreparedStatements"><value>true</value></property>
	     <property name="maxOpenPreparedStatements"><value>20</value></property>
	 </bean>
	<bean id="dataSourceTwo" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
	     <property name="url" value="${hibernate.connection.url2}" />
	     <property name="username"><value>${hibernate.connection.username}</value></property>
	     <property name="password" value="${hibernate.connection.password}" />
	     <property name="filters"><value>stat</value></property>
	     <property name="maxActive"><value>100</value></property>
	     <property name="initialSize"><value>1</value></property>
	     <property name="maxWait"><value>60000</value></property>
	     <property name="minIdle"><value>1</value></property>
	     <property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
	     <property name="minEvictableIdleTimeMillis"><value>300000</value></property>
	     <property name="validationQuery"><value>SELECT 'x'</value></property>
	     <property name="testWhileIdle"><value>true</value></property>
	     <property name="testOnBorrow"><value>false</value></property>
	     <property name="testOnReturn"><value>false</value></property>

	     <property name="poolPreparedStatements"><value>true</value></property>
	     <property name="maxOpenPreparedStatements"><value>20</value></property>
	 </bean>

新增一个动态数据源bean

<bean class="com.test.common.dao.DynamicDataSource" id="dataSourceTarget">
	<property name="targetDataSources"> 
	   <map key-type="java.lang.String"> 
	       <entry value-ref="dataSourceOne" key="one"></entry>
	       <entry value-ref="dataSourceTwo" key="two"></entry>
	   </map> 
	</property> 
	<property name="debug"  value="true"/>
	<property name="defaultTargetDataSource" ref="dataSourceOne" ></property>
</bean>

然后是sessionFactory的设置

<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSourceTarget" />
		<property name="namingStrategy">
			<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
				<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
				<prop key="hibernate.generate_statistics">false</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
		<property name="packagesToScan">
			<list>
				<value>com.test.**.bean</value>
			</list>
		</property>
	</bean>

可以看到动态数据源使用了重新编写的类,具体代码如下

public class DynamicDataSource extends AbstractRoutingDataSource {
	private boolean debug = false;
	Logger log = Logger.getLogger(DynamicDataSource.class);
	private Map<Object, Object> dynamicTargetDataSources;
	private Object dynamicDefaultTargetDataSource; 
	@Override
	protected Object determineCurrentLookupKey() {
		String datasource = DBContextHolder.getDataSource();
		if (debug) {
			if (StringUtils.isEmpty(datasource)) {
				log.info("---当前数据源:默认数据源---");
			} else {
				log.info("---当前数据源:" + datasource + "---");
			}
		}
		return datasource;
	}

	@Override
	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
		super.setTargetDataSources(targetDataSources);
		this.dynamicTargetDataSources = targetDataSources;
	} 

	// 创建数据源
	public boolean createDataSource(String key, String driveClass, String url, String username, String password) {
		try {
			try { // 排除连接不上的错误
				Class.forName(driveClass);
				DriverManager.getConnection(url, username, password);// 相当于连接数据库
			} catch (Exception e) {
				return false;
			}
			@SuppressWarnings("resource")
			DruidDataSource druidDataSource = new DruidDataSource();
			druidDataSource.setName(key);
			druidDataSource.setDriverClassName(driveClass);
			druidDataSource.setUrl(url);
			druidDataSource.setUsername(username);
			druidDataSource.setPassword(password);
			druidDataSource.setMaxWait(60000);
			druidDataSource.setFilters("stat");
			DataSource createDataSource = (DataSource) druidDataSource;
			druidDataSource.init();
			Map<Object, Object> dynamicTargetDataSources2 = this.dynamicTargetDataSources;
			dynamicTargetDataSources2.put(key, createDataSource);// 加入map
			setTargetDataSources(dynamicTargetDataSources2);// 将map赋值给父类的TargetDataSources
			super.afterPropertiesSet();// 将TargetDataSources中的连接信息放入resolvedDataSources管理
			return true;
		} catch (Exception e) {
			log.info(e + "");
			return false;
		}
	} 
	// 删除数据源
	public boolean delDatasources(String datasourceid) {
		Map<Object, Object> dynamicTargetDataSources2 = this.dynamicTargetDataSources;
		if (dynamicTargetDataSources2.containsKey(datasourceid)) {
			Set<DruidDataSource> druidDataSourceInstances = DruidDataSourceStatManager.getDruidDataSourceInstances();
			for (DruidDataSource l : druidDataSourceInstances) {
				if (datasourceid.equals(l.getName())) {
					System.out.println(l);
					dynamicTargetDataSources2.remove(datasourceid);
					DruidDataSourceStatManager.removeDataSource(l);
					setTargetDataSources(dynamicTargetDataSources2);// 将map赋值给父类的TargetDataSources
					super.afterPropertiesSet();// 将TargetDataSources中的连接信息放入resolvedDataSources管理
					return true;
				}
			}
			return false;
		} else {
			return false;
		}
	}

	// 测试数据源连接是否有效
	public boolean testDatasource(String key, String driveClass, String url, String username, String password) {
		try {
			Class.forName(driveClass);
			DriverManager.getConnection(url, username, password);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * Specify the default target DataSource, if any.
	 * <p>
	 * The mapped value can either be a corresponding
	 * {@link javax.sql.DataSource} instance or a data source name String (to be
	 * resolved via a {@link #setDataSourceLookup DataSourceLookup}).
	 * <p>
	 * This DataSource will be used as target if none of the keyed
	 * {@link #setTargetDataSources targetDataSources} match the
	 * {@link #determineCurrentLookupKey()} current lookup key.
	 */
	public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
		super.setDefaultTargetDataSource(defaultTargetDataSource);
		this.dynamicDefaultTargetDataSource = defaultTargetDataSource;
	}


	/**
	 * @param debug
	 *            the debug to set
	 */
	public void setDebug(boolean debug) {
		this.debug = debug;
	}

	/**
	 * @return the debug
	 */
	public boolean isDebug() {
		return debug;
	}

	/**
	 * @return the dynamicTargetDataSources
	 */
	public Map<Object, Object> getDynamicTargetDataSources() {
		return dynamicTargetDataSources;
	}

	/**
	 * @param dynamicTargetDataSources
	 *            the dynamicTargetDataSources to set
	 */
	public void setDynamicTargetDataSources(Map<Object, Object> dynamicTargetDataSources) {
		this.dynamicTargetDataSources = dynamicTargetDataSources;
	}

	/**
	 * @return the dynamicDefaultTargetDataSource
	 */
	public Object getDynamicDefaultTargetDataSource() {
		return dynamicDefaultTargetDataSource;
	}

	/**
	 * @param dynamicDefaultTargetDataSource
	 *            the dynamicDefaultTargetDataSource to set
	 */
	public void setDynamicDefaultTargetDataSource(Object dynamicDefaultTargetDataSource) {
		this.dynamicDefaultTargetDataSource = dynamicDefaultTargetDataSource;
	}
	@Override
	public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO

以上是关于hibernate动态多数据源的主要内容,如果未能解决你的问题,请参考以下文章

具有运行时 pojos 的带有 Hibernate 的 OSGi 片段包

动态 Rstudio 代码片段

Hibernate-Validator框架完成服务端参数据校验(巨详细)

是否可以动态编译和执行 C# 代码片段?

支持动态或静态片段的不同屏幕尺寸?

Java:SpringBoot整合hibernate-validator实现入参数据校验