teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

追記

2021/01/18 23:09

投稿

umau
umau

スコア831

answer CHANGED
@@ -40,4 +40,103 @@
40
40
  <property name="dataSource" ref="dataSource"/> <--コレがRoutingDataSourceをrefしないとダメかも -->
41
41
  </bean>
42
42
  ```
43
- [Spring - データアクセス リファレンスドキュメント](https://spring.pleiades.io/spring-framework/docs/current/reference/html/data-access.html)
43
+ [Spring - データアクセス リファレンスドキュメント](https://spring.pleiades.io/spring-framework/docs/current/reference/html/data-access.html)
44
+
45
+ (追記)
46
+ 「spring.jpa.open-in-view」をfalseにしたら切り替わりました。以下、動いたソースです。
47
+ ```YAML
48
+ spring:
49
+ datasource:
50
+ db1:
51
+ jdbc-url: jdbc:h2:./h2db/db1
52
+ username: dev
53
+ password: dev
54
+ driverClassName: org.h2.Driver
55
+
56
+ db2:
57
+ jdbc-url: jdbc:h2:./h2db/db2
58
+ username: dev
59
+ password: dev
60
+ driverClassName: org.h2.Driver
61
+ jpa:
62
+ open-in-view: false # <--コレ
63
+ hibernate:
64
+ ddl-auto: none
65
+ ```
66
+
67
+ ```java
68
+ @EnableWebMvc
69
+ @Configuration
70
+ public class WebConfig implements WebMvcConfigurer {
71
+
72
+ @Bean
73
+ @Primary
74
+ public RoutingDataSourceResolver multiDataSource() {
75
+ RoutingDataSourceResolver resolver = new RoutingDataSourceResolver();
76
+ Map<Object, Object> dataSources = new HashMap<>();
77
+ dataSources.put(DataSourceType.db1.name(), db1());
78
+ dataSources.put(DataSourceType.db2.name(), db2());
79
+
80
+ resolver.setTargetDataSources(dataSources);
81
+ resolver.setDefaultTargetDataSource(db1());
82
+ return resolver;
83
+ }
84
+
85
+ @Bean
86
+ @ConfigurationProperties(prefix = "spring.datasource.db1")
87
+ public DataSource db1() {
88
+ return DataSourceBuilder.create().build();
89
+ }
90
+
91
+ @Bean
92
+ @ConfigurationProperties(prefix = "spring.datasource.db2")
93
+ public DataSource db2() {
94
+ return DataSourceBuilder.create().build();
95
+ }
96
+ }
97
+ ```
98
+ ```java
99
+ public class DbContextHolder {
100
+
101
+ public enum DataSourceType {
102
+ db1, db2,
103
+ }
104
+
105
+ private static ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();
106
+
107
+ public static void setDataSourceType(DataSourceType type) {
108
+ contextHolder.set(type);
109
+ }
110
+
111
+ public static DataSourceType getDataSourceType() {
112
+ return contextHolder.get();
113
+ }
114
+
115
+ public static void clear() {
116
+ contextHolder.remove();
117
+ }
118
+ }
119
+ ```
120
+ ```java
121
+ @Controller
122
+ public class TestController {
123
+
124
+ @Autowired
125
+ Db1Service service1;
126
+
127
+ @Autowired
128
+ Db2Service service2;
129
+
130
+ @RequestMapping("/test")
131
+ public Object test() {
132
+
133
+ DbContextHolder.setDataSourceType(DataSourceType.db1);
134
+ List<Product> db1List = service1.get();
135
+
136
+ DbContextHolder.setDataSourceType(DataSourceType.db2);
137
+ List<Product> db2List = service2.get();
138
+
139
+ return "OK";
140
+ }
141
+ }
142
+ ```

1

追記

2021/01/18 23:09

投稿

umau
umau

スコア831

answer CHANGED
@@ -27,4 +27,17 @@
27
27
  というところだけに集中してシンプルに作って、動いてから宣言的なやり方に作り替えていくようにしたらどうでしょうか。
28
28
 
29
29
 
30
- ※参考サイトのやり方自体は、Springが用意してくれている仕組みに乗っかって行われているわけなので、もし「このサイトの方法以外の解決はないか?」を質問されているのなら、無い、またはあってもスジが良いとは言えないのでは、と思います。
30
+ ※参考サイトのやり方自体は、Springが用意してくれている仕組みに乗っかって行われているわけなので、もし「このサイトの方法以外の解決はないか?」を質問されているのなら、無い、またはあってもスジが良いとは言えないのでは、と思います。
31
+
32
+
33
+ (追記)
34
+ サービスメソッドに@Transactionalがついているので、TransactionManagerに設定されているDataSourceが使用されているんじゃないでしょうか。
35
+
36
+ そこに作成されたRoutingDataSourceが刺さってない、ということかもしれません。参考サイトは@Transactionalついてないですし、そこ設定するコード含まれてないですね。
37
+
38
+ ```xml
39
+ <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
40
+ <property name="dataSource" ref="dataSource"/> <--コレがRoutingDataSourceをrefしないとダメかも -->
41
+ </bean>
42
+ ```
43
+ [Spring - データアクセス リファレンスドキュメント](https://spring.pleiades.io/spring-framework/docs/current/reference/html/data-access.html)