spring boot 动态数据源配置

本文详细介绍了如何在Spring Boot应用中配置动态数据源,包括创建Maven项目,添加相关依赖,编写启动类,配置application.properties,实现动态数据源路由,注册多数据源,以及编写测试代码进行验证。通过动态数据源路由类和AOP技术,实现了数据源的自动切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)新建maven java project;

    新建一个maven project,取名为:spring-boot-multi-ds

(2)在pom.xml添加依赖包;

   在pom.xml文件中加入依赖的库文件,主要是spring boot基本的,数据库驱动,spring-jpa支持即可,具体pom.xml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
< project  xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
   < modelVersion >4.0.0</ modelVersion >
  
   < groupId >com.kfit</ groupId >
   < artifactId >spring-boot-multids</ artifactId >
   < version >0.0.1-SNAPSHOT</ version >
   < packaging >jar</ packaging >
  
   < name >spring-boot-multids</ name >
   < url >http://maven.apache.org</ url >
  
   < properties >
     < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding >
     <!-- jdk版本号,这里需要你本地进行的jdk进行修改,这里angel使用的是1.8的版本. -->
     < java.version >1.8</ java.version >
   </ properties >
  
  
    <!--
        spring boot 父节点依赖,
        引入这个之后相关的引入就不需要添加version配置,
        spring boot会自动选择最合适的版本进行添加。
        在这里使用的1.3.3版本,可能目前官方有最新的版本了,大家可以
        使用最新的版本。
      -->
     < parent >
        < groupId >org.springframework.boot</ groupId >
        < artifactId >spring-boot-starter-parent</ artifactId >
        < version >1.3.3.RELEASE</ version >
     </ parent >
  
   < dependencies >
     <!-- 单元测试包,在这里没有使用到. -->
     < dependency >
       < groupId >junit</ groupId >
       < artifactId >junit</ artifactId >
       < scope >test</ scope >
     </ dependency >
    
     <!-- spring boot web支持:mvc,aop...
         这个是最基本的,基本每一个基本的demo都是需要引入的。
     -->
     < dependency >
        < groupId >org.springframework.boot</ groupId >
        < artifactId >spring-boot-starter-web</ artifactId >
     </ dependency >
    
     <!-- mysql驱动.
        我们的demo是多数据源,在这里使用Mysql数据库.
     -->
     < dependency >
        < groupId >mysql</ groupId >
        < artifactId >mysql-connector-java</ artifactId >
     </ dependency >
    
    
     <!-- spring jpa
        spring jpa中带有自带的tomcat数据连接池;
        在代码中我们也需要用到.
      -->
     < dependency >
        < groupId >org.springframework.boot</ groupId >
        < artifactId >spring-boot-starter-data-jpa</ artifactId >
     </ dependency >
    
   </ dependencies >
</ project >

在上面的配置文件中都有相应的解释,大家可以自己解读下。

(3)编写启动类App.java

编写spring boot的启动类:

com.kfit.App:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package  com.kfit;
  
import  org.springframework.boot.SpringApplication;
import  org.springframework.boot.autoconfigure.SpringBootApplication;
  
/**
  *
 
  * @version v.0.1
  */
@SpringBootApplication
public  class  App {
     public  static  void  main(String[] args) {
        SpringApplication.run(App. class , args);
     }
}

(4)编写配置文件application.properties;

 在这里主要是多数据源和jpa的配置:

src/main/resources/application.properties:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
########################################################
###配置文件包括 1 个主数据源和多个数据源,
###其中主数据源在Spring中的beanName默认为dataSource,
###另外几个数据源的beanName分包为:ds1、ds2、ds3
###其中datasource的type属性可以具体指定到我们需要的数据源上面,
###不指定情况下默认为:org.apache.tomcat.jdbc.pool.DataSource
###当然你也可以把这些数据源配置到主dataSource数据库中,然后读取数据库生成多数据源。当然这样做的必要性并不大,难不成数据源还会经常变吗。
########################################################
  
# 主数据源,默认的
#spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql: //localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
  
  
# 更多数据源
custom.datasource.names=ds1,ds2,ds3
#custom.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
custom.datasource.ds1.driverClassName =com.mysql.jdbc.Driver
custom.datasource.ds1.url=jdbc:mysql: //localhost:3306/test1
custom.datasource.ds1.username=root
custom.datasource.ds1.password=root
  
#custom.datasource.ds2.type=com.zaxxer.hikari.HikariDataSource
custom.datasource.ds2.driverClassName =com.mysql.jdbc.Driver
custom.datasource.ds2.url=jdbc:mysql: //localhost:3306/test
custom.datasource.ds2.username=root
custom.datasource.ds2.password=root
  
#custom.datasource.ds3.type=com.zaxxer.hikari.HikariDataSource
custom.datasource.ds3.driverClassName =com.mysql.jdbc.Driver
custom.datasource.ds3.url=jdbc:mysql: //localhost:3306/test
custom.datasource.ds3.username=root
custom.datasource.ds3.password=root
  
  
# 下面为连接池的补充设置,应用到上面所有数据源中
spring.datasource.maximum-pool-size= 100
spring.datasource.max-idle= 10
spring.datasource.max-wait= 10000
spring.datasource.min-idle= 5
spring.datasource.initial-size= 5
spring.datasource.validation-query=SELECT  1
spring.datasource.test-on-borrow= false
spring.datasource.test- while -idle= true
spring.datasource.time-between-eviction-runs-millis= 18800
  
  
  
########################################################
### Java Persistence Api
########################################################
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log  for  each sql query
spring.jpa.show-sql =  true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
#[org.hibernate.cfg.ImprovedNamingStrategy  #org.hibernate.cfg.DefaultNamingStrategy]
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

(5)动态数据源路由类;

   动态数据源能进行自动切换的核心就是spring底层提供了AbstractRoutingDataSource类进行数据源的路由的,我们主要继承这个类,实现里面的方法即可实现我们想要的,这里主要是实现方法:determineCurrentLookupKey(),而此方法只需要返回一个数据库的名称即可,所以我们核心的是有一个类来管理数据源的线程池,这个类才是动态数据源的核心处理类。还有另外就是我们使用aop技术在执行事务方法前进行数据源的切换。所以这里有几个需要编码的类,具体如下:

动态数据源上下文>com.kfit.config.datasource.DynamicDataSourceContextHolder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package  com.kfit.config.datasource.dynamic;
  
import  java.util.ArrayList;
import  java.util.List;
  
/**
  * 动态数据源上下文.
  *
 
  * @version v.0.1
  */
public  class  DynamicDataSourceContextHolder {
    
     /*
      * 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
      * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
      */
     private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
     /*
      * 管理所有的数据源id;
      * 主要是为了判断数据源是否存在;
      */
     public static List<String> dataSourceIds = new ArrayList<String>();
  
     /**
      * 使用setDataSourceType设置当前的
      * @param dataSourceType
      */
     public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
     }
  
     public static String getDataSourceType() {
        return contextHolder.get();
     }
  
     public static void clearDataSourceType() {
        contextHolder.remove();
     }
    
     /**
      * 判断指定DataSrouce当前是否存在
      *
      * @param dataSourceId
      * @return
      * @author SHANHY
      * @create  2016年1月24日
      */
     public  static  boolean  containsDataSource(String dataSourceId){
         return  dataSourceIds.contains(dataSourceId);
     }
}

数据源路由类>com.kfit.config.datasource.dynamic.DynamicDataSource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package  com.kfit.config.datasource.dynamic;
  
import  org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  
/**
  * 动态数据源.
  *
  * @version v.0.1
  */
public  class  DynamicDataSource  extends  AbstractRoutingDataSource {
    
     /*
      * 代码中的determineCurrentLookupKey方法取得一个字符串,
      * 该字符串将与配置文件中的相应字符串进行匹配以定位数据源,配置文件,即applicationContext.xml文件中需要要如下代码:(non-Javadoc)
      * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
      */
     @Override
     protected Object determineCurrentLookupKey() {
        /*
         * DynamicDataSourceContextHolder代码中使用setDataSourceType
         * 设置当前的数据源,在路由类中使用getDataSourceType进行获取,
         *  交给AbstractRoutingDataSource进行注入使用。
         */
        return  DynamicDataSourceContextHolder.getDataSourceType();
     }
}

指定数据源注解类>com.kfit.config.datasource.dynamic.TargetDataSource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package  com.kfit.config.datasource.dynamic;
  
import  java.lang.annotation.Documented;
import  java.lang.annotation.ElementType;
import  java.lang.annotation.Retention;
import  java.lang.annotation.RetentionPolicy;
import  java.lang.annotation.Target;
  
/**
  * 在方法上使用,用于指定使用哪个数据源
 
  * @version v.0.1
  */
@Target ({ ElementType.METHOD, ElementType.TYPE })
@Retention (RetentionPolicy.RUNTIME)
@Documented
public  @interface  TargetDataSource {
     String value();
}

切换数据源Advice>com.kfit.config.datasource.dynamic.DynamicDataSourceAspect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package  com.kfit.config.datasource.dynamic;
  
import  org.aspectj.lang.JoinPoint;
import  org.aspectj.lang.annotation.After;
import  org.aspectj.lang.annotation.Aspect;
import  org.aspectj.lang.annotation.Before;
import  org.springframework.core.annotation.Order;
import  org.springframework.stereotype.Component;
  
/**
  * 切换数据源Advice
 
  * @version v.0.1
  */
@Aspect
@Order (- 10 ) //保证该AOP在@Transactional之前执行
@Component
public  class  DynamicDataSourceAspect {
    
     /*
      * @Before("@annotation(ds)")
      * 的意思是:
      *
      * @Before:在方法执行之前进行执行:
      * @annotation(targetDataSource):
      * 会拦截注解targetDataSource的方法,否则不拦截;
      */
     @Before ( "@annotation(targetDataSource)" )
     public  void  changeDataSource(JoinPoint point, TargetDataSourcetargetDataSource)  throws  Throwable {
        //获取当前的指定的数据源;
         String dsId = targetDataSource.value();
         //如果不在我们注入的所有的数据源范围之内,那么输出警告信息,系统自动使用默认的数据源。
         if  (!DynamicDataSourceContextHolder.containsDataSource(dsId)) {
             System.err.println( "数据源[{}]不存在,使用默认数据源 > {}" +targetDataSource.value()+point.getSignature());
         else  {
             System.out.println( "Use DataSource : {} > {}" +targetDataSource.value()+point.getSignature());
             //找到的话,那么设置到动态数据源上下文中。
             DynamicDataSourceContextHolder.setDataSourceType(targetDataSource.value());
         }
     }
    
     @After ( "@annotation(targetDataSource)" )
     public  void  restoreDataSource(JoinPoint point, TargetDataSourcetargetDataSource) {
        System.out.println( "Revert DataSource : {} > {}" +targetDataSource.value()+point.getSignature());
        //方法执行完毕之后,销毁当前数据源信息,进行垃圾回收。
         DynamicDataSourceContextHolder.clearDataSourceType();
     }
    
}

(6)注册多数据源;

   以上都是动态数据源在注入的时候使用的代码,其实很重要的一部分代码就是注册我们在application.properties配置的多数据源,这才是重点,这里我们使用

ImportBeanDefinitionRegistrar进行注册,具体的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package  com.kfit.config.datasource.dynamic;
  
import  java.util.HashMap;
import  java.util.Map;
  
import  javax.sql.DataSource;
  
import  org.springframework.beans.MutablePropertyValues;
import  org.springframework.beans.PropertyValues;
import  org.springframework.beans.factory.support.BeanDefinitionRegistry;
import  org.springframework.beans.factory.support.GenericBeanDefinition;
import  org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import  org.springframework.boot.bind.RelaxedDataBinder;
import  org.springframework.boot.bind.RelaxedPropertyResolver;
import  org.springframework.context.EnvironmentAware;
import  org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import  org.springframework.core.convert.ConversionService;
import  org.springframework.core.convert.support.DefaultConversionService;
import  org.springframework.core.env.Environment;
import  org.springframework.core.type.AnnotationMetadata;
  
/**
  * 动态数据源注册;
  *
  * @version v.0.1
  */
public  class  DynamicDataSourceRegister   implements  ImportBeanDefinitionRegistrar, EnvironmentAware {
    
     //如配置文件中未指定数据源类型,使用该默认值
     private  static  final  Object DATASOURCE_TYPE_DEFAULT =  "org.apache.tomcat.jdbc.pool.DataSource" ;
     private  ConversionService conversionService =  new  DefaultConversionService();
     private  PropertyValues dataSourcePropertyValues;
    
     // 默认数据源
     private  DataSource defaultDataSource;
    
     private  Map<String, DataSource> customDataSources =  new  HashMap<String, DataSource>();
    
     /**
      * 加载多数据源配置
      */
     @Override
     public  void  setEnvironment(Environment environment) {
        System.out.println( "DynamicDataSourceRegister.setEnvironment()" );
        initDefaultDataSource(environment);
         initCustomDataSources(environment);
     }
    
     /**
      * 加载主数据源配置.
      * @param env
      */
     private  void  initDefaultDataSource(Environment env){
        // 读取主数据源
        RelaxedPropertyResolver propertyResolver =  new  RelaxedPropertyResolver(env,  "spring.datasource." );
        Map<String, Object> dsMap =  new  HashMap<String, Object>();
        dsMap.put( "type" , propertyResolver.getProperty( "type" ));
         dsMap.put( "driverClassName" , propertyResolver.getProperty( "driverClassName" ));
         dsMap.put( "url" , propertyResolver.getProperty( "url" ));
         dsMap.put( "username" , propertyResolver.getProperty( "username" ));
         dsMap.put( "password" , propertyResolver.getProperty( "password" ));
        
         //创建数据源;
         defaultDataSource = buildDataSource(dsMap);
         dataBinder(defaultDataSource, env);
     }
    
     /**
      * 初始化更多数据源
      *
      * @author SHANHY
      * @create 2016年1月24日
      */
     private  void  initCustomDataSources(Environment env) {
         // 读取配置文件获取更多数据源,也可以通过defaultDataSource读取数据库获取更多数据源
         RelaxedPropertyResolver propertyResolver =  new  RelaxedPropertyResolver(env,  "custom.datasource." );
         String dsPrefixs = propertyResolver.getProperty( "names" );
         for  (String dsPrefix : dsPrefixs.split( "," )) { // 多个数据源
             Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix +  "." );
             DataSource ds = buildDataSource(dsMap);
             customDataSources.put(dsPrefix, ds);
             dataBinder(ds, env);
         }
     }
    
     /**
      * 创建datasource.
      * @param dsMap
      * @return
      */
     @SuppressWarnings ( "unchecked" )
     public  DataSource buildDataSource(Map<String, Object> dsMap) {
        Object type = dsMap.get( "type" );
         if  (type ==  null ){
             type = DATASOURCE_TYPE_DEFAULT; // 默认DataSource
         }
         Class<?  extends  DataSource> dataSourceType;
        
        try  {
            dataSourceType = (Class<?  extends  DataSource>) Class.forName((String) type);
            String driverClassName = dsMap.get( "driverClassName" ).toString();
             String url = dsMap.get( "url" ).toString();
             String username = dsMap.get( "username" ).toString();
             String password = dsMap.get( "password" ).toString();
             DataSourceBuilder factory =   DataSourceBuilder.create().driverClassName(driverClassName).url(url).username(username).password(password).type(dataSourceType);
             returnfactory.build();
        catch  (ClassNotFoundException e) {
            e.printStackTrace();
        }
        returnnull;
     }
    
     /**
      * 为DataSource绑定更多数据
      * @param dataSource
      * @param env
      */
     private  void  dataBinder(DataSource dataSource, Environment env){
        RelaxedDataBinder dataBinder =  new  RelaxedDataBinder(dataSource);
        dataBinder.setConversionService(conversionService);
        dataBinder.setIgnoreNestedProperties( false ); //false
         dataBinder.setIgnoreInvalidFields( false ); //false
         dataBinder.setIgnoreUnknownFields( true ); //true
        
         if (dataSourcePropertyValues ==  null ){
             Map<String, Object> rpr =  new  RelaxedPropertyResolver(env,  "spring.datasource" ).getSubProperties( "." );
             Map<String, Object> values =  new  HashMap<>(rpr);
             // 排除已经设置的属性
             values.remove( "type" );
             values.remove( "driverClassName" );
             values.remove( "url" );
             values.remove( "username" );
             values.remove( "password" );
             dataSourcePropertyValues =  new  MutablePropertyValues(values);
         }
         dataBinder.bind(dataSourcePropertyValues);
        
     }
    
  
     @Override
     public  void  registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println( "DynamicDataSourceRegister.registerBeanDefinitions()" );
        Map<Object, Object> targetDataSources =  new  HashMap<Object, Object>();
        // 将主数据源添加到更多数据源中
         targetDataSources.put( "dataSource" , defaultDataSource);
         DynamicDataSourceContextHolder.dataSourceIds.add( "dataSource" );
         // 添加更多数据源
         targetDataSources.putAll(customDataSources);
         for  (String key : customDataSources.keySet()) {
             DynamicDataSourceContextHolder.dataSourceIds.add(key);
         }
        
         // 创建DynamicDataSource
         GenericBeanDefinition beanDefinition =  new  GenericBeanDefinition();
         beanDefinition.setBeanClass(DynamicDataSource. class );
        
         beanDefinition.setSynthetic( true );
         MutablePropertyValues mpv = beanDefinition.getPropertyValues();
         //添加属性:AbstractRoutingDataSource.defaultTargetDataSource
         mpv.addPropertyValue( "defaultTargetDataSource" , defaultDataSource);
         mpv.addPropertyValue( "targetDataSources" , targetDataSources);
         registry.registerBeanDefinition( "dataSource" , beanDefinition);
     }
  
}

这里还有一个步骤很重要,由于我们是使用的ImportBeanDefinitionRegistrar的方式进行注册的,所以我们需要在App.java类中使用@Import进行注册,具体改造之后的App.java代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package  com.kfit;
  
import  org.springframework.boot.SpringApplication;
import  org.springframework.boot.autoconfigure.SpringBootApplication;
import  org.springframework.context.annotation.Import;
import  com.kfit.config.datasource.dynamic.DynamicDataSourceRegister;
  
/**
  *
 
  * @version v.0.1
  */
@SpringBootApplication
//注册动态多数据源
@Import ({DynamicDataSourceRegister. class })
public  class  App {
     public  static  void  main(String[] args) {
        SpringApplication.run(App. class , args);
     }
}

(7)测试类测试;

 核心的代码都编写完毕了,当然我们肯定是需要编写代码进行测试下,我们才放心了。

com.kfit.demo.bean.Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package  com.kfit.demo.bean;
  
import  javax.persistence.Entity;
import  javax.persistence.GeneratedValue;
import  javax.persistence.Id;
  
/**
  * 测试demo类.
 
  * @version v.0.1
  */
@Entity
public  class  Demo {
     @Id  @GeneratedValue
     private  longid;
    
     private  String name;
  
     public  long  getId() {
        return  id;
     }
  
     public  void  setId(longid) {
        this .id = id;
     }
  
     public  String getName() {
        return  name;
     }
  
     publicvoid setName(String name) {
        this .name = name;
     }
  
     @Override
     public  String toString() {
        return "Demo [id="  + id +  ", name="  + name +  "]" ;
     }
}

com.kfit.demo.dao.TestDao:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package  com.kfit.demo.dao;
  
import  java.sql.ResultSet;
import  java.sql.SQLException;
import  java.util.List;
  
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.jdbc.core.JdbcTemplate;
import  org.springframework.jdbc.core.RowMapper;
import  org.springframework.stereotype.Service;
  
import  com.kfit.demo.bean.Demo;
  
@Service
public  class  TestDao {
    
     @Autowired
     private  JdbcTemplate jdbcTemplate;
    
     /**
      * 不指定数据源使用默认数据源
      * @return
      */
     public  List<Demo> getList(){
        String sql =  "select *from Demo" ;
         return  (List<Demo>) jdbcTemplate.query(sql,  new  RowMapper<Demo>(){
             @Override
             public  Demo mapRow(ResultSet rs, introwNum)  throws  SQLException {
                 Demo demo =  new  Demo();
                 demo.setId(rs.getLong( "id" ));
                 demo.setName(rs.getString( "name" ));;
                 returndemo;
             }
         });
     }
    
      /**
      * 指定数据源
      * 在对应的service进行指定;
      * @return
      * @author SHANHY
      * @create  2016年1月24日
      */
     public  List<Demo> getListByDs1(){
         /*
          * 这张表示复制的主库到ds1的,在ds中并没有此表.
          * 需要自己自己进行复制,不然会报错:Table 'test1.demo1' doesn't exist
          */
        String sql =  "select *from Demo1" ;
         return  (List<Demo>) jdbcTemplate.query(sql,  new  RowMapper<Demo>(){
  
             @Override
             public  Demo mapRow(ResultSet rs, introwNum)  throws  SQLException {
                 Demo demo =  new  Demo();
                 demo.setId(rs.getLong( "id" ));
                 demo.setName(rs.getString( "name" ));;
                 returndemo;
             }
  
         });
     }
}

com.kfit.demo.service.TestService :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package  com.kfit.demo.service;
  
import  java.util.List;
  
import  javax.annotation.Resource;
  
import  org.springframework.stereotype.Service;
  
import  com.kfit.config.datasource.dynamic.TargetDataSource;
import  com.kfit.demo.bean.Demo;
import  com.kfit.demo.dao.TestDao;
  
@Service
public  class  TestService {
    
     @Resource
     private  TestDao testDao;
    
     /**
      * 不指定数据源使用默认数据源
      * @return
      */
     public  List<Demo> getList(){
        returntestDao.getList();
     }
    
     /**
      * 指定数据源
      * @return
      */
     @TargetDataSource ( "ds1" )
     public  List<Demo> getListByDs1(){
         returntestDao.getListByDs1();
     }
}

com.kfit.demo.controller.TestController:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package  com.kfit.demo.controller;
  
import  javax.annotation.Resource;
  
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.RestController;
  
import  com.kfit.demo.bean.Demo;
import  com.kfit.demo.service.TestService;
  
@RestController
public  class  TestController {
    
     @Resource
     private  TestService testService;
    
     @RequestMapping ( "/test1" )
     public  String test(){
//     for(Demo d:testService.getList()){
//         System.out.println(d);
//     }
        for (Demo d:testService.getListByDs1()){
            System.out.println(d);
        }
        return "ok" ;
     }
    
}

好了,测试代码就这么多了,运行App.java进行测试把,访问:

http://127.0.0.1:8080/test1 查看控制台的打印。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值