在SpringSide 2.0中利用多个数据库
副标题#e#
为了提高网站未来向外扩展的本领,我是用了数据支解的架构,这就要求我的网站可以或许机动的会见多个数据库,假如是直接操纵JDBC,这基础就不成问题。可是在SpringSide2.0中,由于集成了Hibernate,所以对数据的会见大部门时候都是通过设置实现的。
要想在SpringSide2.0中利用多个数据库,最简朴的步伐就是设置多个sessionFactory,下面是我的摸索步调。
首先,要修改src/resources/config目次下的jdbc.properties文件,界说多个数据库的毗连,如下:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.urlYumDaysIndex=jdbc:mysql://localhost:3306/YumDaysIndex?useUnicode=true&characterEncoding=utf8
jdbc.urlYumDays001=jdbc:mysql://localhost:3306/YumDays001?useUnicode=true&characterEncoding=utf8
然后,修改src/resources/spring目次下的dataAccessContext-hibernate.xml文件,界说多个数据源,它们之间只有url属性差异:
<!-- 数据源界说,利用Apache DBCP 毗连池 -->
<bean id="dataSourceYumDaysIndex" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.urlYumDaysIndex}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 数据源界说,利用Apache DBCP 毗连池 -->
<bean id="dataSourceYumDays001" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.urlYumDays001}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
然后,照旧修改这个文件,界说多个sessionFactory,它们之间只有数据源的属性差异:
<!--Hibernate SessionFatory-->
<bean id="sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSourceYumDaysIndex"/>
<property name="annotatedClasses">
<list>
<value>com.yumdays.model.Catalog</value>
<value>com.yumdays.model.Statistic</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<!-- see /components/orm/hibernate/meta/dialect.properties for all Dialect -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
</bean>
<!--Hibernate SessionFatory-->
<bean id="sessionFactory001" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSourceYumDays001"/>
<property name="annotatedClasses">
<list>
</list>
</property>
<property name="hibernateProperties">
<props>
<!-- see /components/orm/hibernate/meta/dialect.properties for all Dialect -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
</bean>
#p#副标题#e#
再然后,照旧修改这个文件,界说多个差异的事务打点器,它们之间只有sessionFactory属性差异,如下:
#p#分页标题#e#
<!--Hibernate TransactionManager-->
<bean id="transactionManagerIndex" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
<bean id="transactionManager001" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory001"/>
</bean>
以上的这些修改是最根基的,就是把sessionFactory和事务打点器都界说为多份的,今后,在要利用到这些对象的时候,就不能利用Spring提供的自动凭据name匹配的利便了,必需得本身指定。
操作SpringSide2.0,只需要编写暗示Model的POJO,就可以很容易获得数据会见层的代码,好比,我的网站有一个暗示文章分类的数据表,其对应的Model如下:
package com.yumdays.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="catalogs")
public class Catalog implements Serializable {
private String id;
private String name;
@Id
@GenericGenerator(name="system-uuid",strategy="uuid")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
那么,其DAO层的代码如下:
package com.yumdays.service;
import org.springside.core.dao.HibernateEntityDao;
import com.yumdays.model.Catalog;
public class CatalogManager extends HibernateEntityDao<Catalog> {
}
相当的简捷,该CatalogManager类提供了很是完整的find、get、save等成果。下一步,将这个类是用Spring打点起来的时候,就必需本身指定sessionFactory了,因此,在src/resources/spring/目次下的serviceContext.xml文件中,设置的形式如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-lazy-init="true" default-autowire="byName">
<bean id="catalogManager" class="com.yumdays.service.CatalogManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
<bean id="statisticManager" class="com.yumdays.service.StatisticManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
</beans>
至于事务打点器,是在设置事务的时候用到的,因此,修改src/resources/spring目次下的applicationContext.xml文件,如下:
<!-- 以AspectJ方法 界说 AOP -->
<aop:config proxy-target-class="true">
<!-- 留意,请把第2个*号换为项目package -->
<aop:advisor pointcut="execution(* *..service.CatalogManager.*(..))" advice-ref="txAdviceIndex"/>
<aop:advisor pointcut="execution(* *..service.StatisticManager.*(..))" advice-ref="txAdviceIndex"/>
</aop:config>
<!-- 基才干务界说,利用transactionManager作事务打点,默认get*要领的事务为readonly,其余要领按默认配置.
默认的配置请参考Spring文档事务一章. -->
<tx:advice id="txAdviceIndex" transaction-manager="transactionManagerIndex">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
#p#分页标题#e#
OK,快速启动项目,可是照旧没有乐成,报出的错误提示说没有界说name为transactionManager的bean。颠末我这么一改,虽然没有界说这个bean了,可是我也没有用它啊?我用的是transactionManagerIndex,颠末多次排查,我仍然没有找出问题的症结地址。
另外,在web.xml文件中设置的org.springframework.orm.hibernate3.support.OpenSessionInViewFilter也起不到浸染了,因为我不知道这个类能不能打点多个SessionFactory,好像是不可的。
由此可见,利用默认值的处所太多了,也是会害死人的。我已经向SpringSide的老大江南白衣请教这个问题了,临时还没有获得回覆。
为了使我的项目可以或许顺利继承,我只有采纳别的的变通要领,那就是把YumDaysIndex和YumDaysContent作为两个差异的项目别分开拓。可是这样并不可以或许一劳永逸,未来当数据库的负载到达极限,需要让主从数据库处事器分隔,主处事器只提供写操纵,从处事器只提供读操纵,我还得把写数据库和读数据库的代码分到差异的项目中举办开拓。