Heim >Java >javaLernprogramm >Vertiefendes Verständnis der Spring-Konfiguration mehrerer Datenquellen
In Projekten stoßen wir häufig auf das Problem mehrerer Datenquellen, insbesondere bei Projekten wie der Datensynchronisierung oder geplanten Aufgaben. Das größte Problem bei mehreren Datenquellen besteht nicht in der Konfiguration mehrerer Datenquellen, sondern darin, wie man Datenquellen flexibel und dynamisch wechseln kann. Beispielsweise konfigurieren wir in einem Spring- und Hibernate-Framework-Projekt häufig eine Datenquelle, um eine Verbindung zur Datenbank in der Spring-Konfiguration herzustellen, binden sie dann an die SessionFactory und geben dann die SessionFactory im Dao-Layer-Code an, um Datenbankoperationen auszuführen.
Wie im Bild oben gezeigt, ist jeder Block gekennzeichnet und verknüpft. Wenn mehrere Datenquellen vorhanden sind, kann dies nur so sein, wie im Bild unten gezeigt.
Es ist ersichtlich, dass zwei SessionFactory im Dao-Layer-Code fest codiert sind. Wenn also in Zukunft eine weitere Datenquelle vorhanden ist, muss der Code zum Hinzufügen geändert werden Eine SessionFactory entspricht offensichtlich nicht dem Öffnungs- und Schließprinzip.
Dann sollte der richtige Ansatz sein:
Der Code lautet wie folgt:
1. applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd"> <context:annotation-config /> <context:component-scan base-package="com"></context:component-scan> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:com/resource/config.properties</value> </list> </property> </bean> <bean id="dataSourceOne" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${dbOne.jdbc.driverClass}" /> <property name="jdbcUrl" value="${dbOne.jdbc.url}" /> <property name="user" value="${dbOne.jdbc.user}" /> <property name="password" value="${dbOne.jdbc.password}" /> <property name="initialPoolSize" value="${dbOne.jdbc.initialPoolSize}" /> <property name="minPoolSize" value="${dbOne.jdbc.minPoolSize}" /> <property name="maxPoolSize" value="${dbOne.jdbc.maxPoolSize}" /> </bean> <bean id="dataSourceTwo" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${dbTwo.jdbc.driverClass}" /> <property name="jdbcUrl" value="${dbTwo.jdbc.url}" /> <property name="user" value="${dbTwo.jdbc.user}" /> <property name="password" value="${dbTwo.jdbc.password}" /> <property name="initialPoolSize" value="${dbTwo.jdbc.initialPoolSize}" /> <property name="minPoolSize" value="${dbTwo.jdbc.minPoolSize}" /> <property name="maxPoolSize" value="${dbTwo.jdbc.maxPoolSize}" /> </bean> <bean id="dynamicDataSource" class="com.core.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSourceOne" key="dataSourceOne"></entry> <entry value-ref="dataSourceTwo" key="dataSourceTwo"></entry> </map> </property> <property name="defaultTargetDataSource" ref="dataSourceOne"> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dynamicDataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hbm2ddl.auto">create</prop> </props> </property> <property name="packagesToScan"> <list> <value>com.po</value> </list> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <aop:config> <aop:pointcut id="transactionPointCut" expression="execution(* com.dao..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointCut" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <aop:config> <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"> <aop:pointcut id="daoOne" expression="execution(* com.dao.one.*.*(..))" /> <aop:pointcut id="daoTwo" expression="execution(* com.dao.two.*.*(..))" /> <aop:before pointcut-ref="daoOne" method="setdataSourceOne" /> <aop:before pointcut-ref="daoTwo" method="setdataSourceTwo" /> </aop:aspect> </aop:config> </beans>
2. DynamicDataSource.class
package com.core; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getCustomerType(); } }
3. DatabaseContextHolder.class
package com.core; public class DatabaseContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setCustomerType(String customerType) { contextHolder.set(customerType); } public static String getCustomerType() { return contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } }
4. DataSourceInterceptor.class
package com.core; import org.aspectj.lang.JoinPoint; import org.springframework.stereotype.Component; @Component public class DataSourceInterceptor { public void setdataSourceOne(JoinPoint jp) { DatabaseContextHolder.setCustomerType("dataSourceOne"); } public void setdataSourceTwo(JoinPoint jp) { DatabaseContextHolder.setCustomerType("dataSourceTwo"); } }
5. po-Entitätsklasse
package com.po; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "BTSF_BRAND", schema = "hotel") public class Brand { private String id; private String names; private String url; @Id @Column(name = "ID", unique = true, nullable = false, length = 10) public String getId() { return this.id; } public void setId(String id) { this.id = id; } @Column(name = "NAMES", nullable = false, length = 50) public String getNames() { return this.names; } public void setNames(String names) { this.names = names; } @Column(name = "URL", length = 200) public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } }
package com.po; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "CITY", schema = "car") public class City { private Integer id; private String name; @Id @Column(name = "ID", unique = true, nullable = false) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name = "NAMES", nullable = false, length = 50) public String getName() { return name; } public void setName(String name) { this.name = name; } }
6. BrandDaoImpl.class
package com.dao.one; import java.util.List; import javax.annotation.Resource; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.springframework.stereotype.Repository; import com.po.Brand; @Repository public class BrandDaoImpl implements IBrandDao { @Resource protected SessionFactory sessionFactory; @SuppressWarnings("unchecked") @Override public List<Brand> findAll() { String hql = "from Brand"; Query query = sessionFactory.getCurrentSession().createQuery(hql); return query.list(); } }
package com.dao.two; import java.util.List; import javax.annotation.Resource; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.springframework.stereotype.Repository; import com.po.City; @Repository public class CityDaoImpl implements ICityDao { @Resource private SessionFactory sessionFactory; @SuppressWarnings("unchecked") @Override public List<City> find() { String hql = "from City"; Query query = sessionFactory.getCurrentSession().createQuery(hql); return query.list(); } }8. DaoTest.class
package com.test; import java.util.List; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import com.dao.one.IBrandDao; import com.dao.two.ICityDao; import com.po.Brand; import com.po.City; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:com/resource/applicationContext.xml") @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) public class DaoTest { @Resource private IBrandDao brandDao; @Resource private ICityDao cityDao; @Test public void testList() { List<Brand> brands = brandDao.findAll(); System.out.println(brands.size()); List<City> cities = cityDao.find(); System.out.println(cities.size()); } }Verwenden Sie aop, um die Datenquelle dynamisch zu ändern. Wenn wir eine Datenquelle hinzufügen müssen, müssen wir nur die AOP-Konfiguration in der applicationContext-Konfigurationsdatei hinzufügen und einen neuen DataSourceInterceptor erstellen. ohne irgendeinen Code zu ändern.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er zum Lernen aller beiträgt. Ich hoffe auch, dass jeder die PHP-Chinesisch-Website unterstützt.