Spring AbstractRoutingDataSource 使用教程

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(630)   2023-03-28 11:29:14
AbstractRoutingDataSource是一个非常有用的功能,如果我们的设计允许基于某些标准的多个数据库,这些标准可能会因每个用户请求而改变。例如,当用户属于某个语言环境时,我们可以使用特定的数据库,如果用户属于另一个语言环境,则切换到另一个语言环境。
AbstractRoutingDataSource是一种抽象数据源实现,它getConnection()根据查找键将调用路由到各种目标数据源之一。后者通常(但不一定)通过一些线程绑定的事务上下文来确定。
让我们看看一个例子来使用AbstractRoutingDataSource用于选择用于基于它们的区域的用户适当的数据源
在给定的示例中,我们仅配置了两个语言环境“en”和“es”。我们可以配置任意数量的数据源。此外,区域设置不仅是更改数据源的唯一标准。如果您有其他一些要求,请随意添加您自己的逻辑。

AbstractRoutingDataSource 示例

1.1. 扩展 AbstractRoutingDataSource

这是必需的,因为在这里我们将决定我们想要在哪种情况下使用哪个数据源。
 

import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
public class MyRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        String language = LocaleContextHolder.getLocale().getLanguage();
        System.out.println("Language obtained: "+ language);
        return language;
    }
}

1.2. 配数据源
首先配置各种数据源,而不必担心它们将如何被访问。

<bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassName}"
    p:username="${jdbc.username}"
    p:password="${jdbc.password}" />
 
<bean id="concreteDataSourceOne"
    parent="abstractDataSource"
    p:url="${jdbc.databaseurlOne}"/>
  
<bean id="concreteDataSourceTwo"
    parent="abstractDataSource"
    p:url="${jdbc.databaseurlTwo}"/>

1.3. 设置路由

在这里,我们将为上述步骤中所有配置的数据源实际定义键值对 [“targetDataSources”]。值将是数据源 bean 名称,键将是来自determineCurrentLookupKey()方法 in 的结果MyRoutingDataSource
如果任何用户请求都找不到任何内容,我们还可以提及默认数据源。如果将是默认值并防止异常。

<bean id="dataSource" class="com.howtodoinjava.controller.MyRoutingDataSource">
   <property name="targetDataSources">
      <map key-type="java.lang.String">
         <entry key="en" value-ref="concreteDataSourceOne"/>
         <entry key="es" value-ref="concreteDataSourceTwo"/>
      </map>
   </property>
   <!-- <property name="defaultTargetDataSource" ref="concreteDataSourceOne"/> -->
</bean>

1.4. 弹簧配置

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" /> <!-- HERE -->
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

在所有更改之后,您的弹簧配置将如下所示:
 

<?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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
  
    <context:annotation-config />
    <context:component-scan base-package="com.howtodoinjava.controller" />
  
    <bean id="jspViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
  
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        p:location="/WEB-INF/jdbc.properties" />
     
    <!-- Step 3 -->
     
     <bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="${jdbc.driverClassName}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}" />
  
    <bean id="concreteDataSourceOne"
        parent="abstractDataSource"
        p:url="${jdbc.databaseurlOne}"/>
      
     <bean id="concreteDataSourceTwo"
        parent="abstractDataSource"
        p:url="${jdbc.databaseurlTwo}"/>
      
      <!-- Step 4 -->
      
     <bean id="dataSource" class="com.howtodoinjava.controller.MyRoutingDataSource">
       <property name="targetDataSources">
          <map key-type="java.lang.String">
             <entry key="en" value-ref="concreteDataSourceOne"/>
             <entry key="es" value-ref="concreteDataSourceTwo"/>
          </map>
       </property>
       <!-- <property name="defaultTargetDataSource" ref="concreteDataSourceOne"/> -->
    </bean>
     
     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
          p:basenames="messages" />
     
    <!-- Declare the Interceptor -->
    <mvc:interceptors>    
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
              p:paramName="locale" />
    </mvc:interceptors>
     
    <!-- Declare the Resolver -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
     
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
     
    <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDaoImpl"></bean>
    <bean id="employeeManager" class="com.howtodoinjava.service.EmployeeManagerImpl"></bean>
  
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
     
</beans>

2. 演示
在测试应用程序之前,我们已经在其中创建了两个数据库模式和两个相似的表。除了其中的数据外,两个表完全相同。我故意保持不同,以证明两个不同的请求实际上正在访问不同的数据库。

delimiter $$
 
CREATE DATABASE 'test' /*!40100 DEFAULT CHARACTER SET latin1 */$$
 
USE test$$
 
CREATE TABLE 'employee' (
  'ID' int(11) NOT NULL AUTO_INCREMENT,
  'FIRSTNAME' varchar(30) DEFAULT NULL,
  'LASTNAME' varchar(30) DEFAULT NULL,
  'TELEPHONE' varchar(15) DEFAULT NULL,
  'EMAIL' varchar(30) DEFAULT NULL,
  'CREATED' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY ('ID')
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1$$
 
INSERT INTO 'test'.'employee' ('ID','FIRSTNAME','LASTNAME','TELEPHONE','EMAIL','CREATED') 
VALUES (4,'Lokesh','Gupta','9811111111','howtodoinjava@gmail.com',CURRENT_TIMESTAMP);
 
CREATE DATABASE 'testtwo' /*!40100 DEFAULT CHARACTER SET latin1 */$$
 
USE testtwo$$
 
CREATE TABLE 'employee' (
  'ID' int(11) NOT NULL AUTO_INCREMENT,
  'FIRSTNAME' varchar(30) DEFAULT NULL,
  'LASTNAME' varchar(30) DEFAULT NULL,
  'TELEPHONE' varchar(15) DEFAULT NULL,
  'EMAIL' varchar(30) DEFAULT NULL,
  'CREATED' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY ('ID')
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1$$
 
INSERT INTO 'testtwo'.'employee' ('ID','FIRSTNAME','LASTNAME','TELEPHONE','EMAIL','CREATED') 
VALUES (1,'Rakesh','Shukla','1234','email',CURRENT_TIMESTAMP);

1)点击网址:http://localhost:8080/Spring3.2.5Hibernate4.0.1Integration/?locale=en
AbstractRoutingDataSource_example_locale_en
2)点击网址:http://localhost:8080/Spring3.2.5Hibernate4.0.1Integration/?locale=es
AbstractRoutingDataSource_example_locale_es
3)点击网址:http://localhost:8080/Spring3.2.5Hibernate4.0.1Integration/?locale=fr
这将导致异常,因为我们既没有为此语言环境设置任何数据源,也没有设置任何默认数据源 [注释行]。

HTTP Status 500 - Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [fr]
 
type Exception report
 
message Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [fr]

 
地址:https://www.leftso.com/article/882.html

相关阅读

AbstractRoutingDataSource是一个非常有用的功能,如果我们的设计允许基于某些标准的多个数据库,这些标准可能会因每个用户请求而改变
引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写...
Spring Boot 2.0,Spring框架的Spring Boot 中的Spring Boot Actuator变化讲解。并且了解如何在Spring Boot 2.0中使用Actuator...
spring boot 1.5整合redis实现spring的缓存框架,spring boot,redis
Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取properties配置文件值 Spring Boot 2.0获取properties配...
spring boot是一个崭新的spring框架分支项目,本文讲解基本的数据库配置
spring boot入门,spring boot是一个崭新的spring框架分支项目,本文讲解其属性配置相关
spring boot 入门之整合spring session实现session共享。一直以来Java编程中web项目中的session共享问题都是一个很难解决的问题。接下来将讲解通过sprin...
spring boot 入门之spring session实现restful apis。通过spring boot或者spring mvc整合spring session的方式来实现sessio...
spring boot又一个spring框架的经典项目,本文讲解spring boot入门的环境配置以及第一个项目,Spring Boot 入门教程