일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 대댓글
- 비동기
- Spring
- modal #alert #sweetalert #sweetAlert #모달
- CRUD
- Controller
- deferred
- Boot
- 우리마
- SpringFramework
- DAO
- paginationInfo
- REST
- egov
- 외부접속
- Today
- Total
우리마의 웹 개발
[eGovFramework]하나의 프로젝트에서 2개의 DB 사용 하기(Postgresql, Tibero DB) 본문
안녕하세요. 이번 글에서는 eGovFramework3.8 환경에서 두 개의 DBMS를 붙이는 방법에 대해서 끄적이려고 해요. 필자는 기존에 Postgresql을 사용하다가 Tibero DB를 붙였어요. 해당 DB의 드라이버는 maven repository에서 가져와서 pom.xml에 추가해주시면 됩니다.
context-datasource.xml 설정 - Datasource 추가 하기
먼저 datasource를 추가해줘야 합니다.
src/main/resource/egovframework/spring 아래에 context-datasource.xml 파일이 있습니다.
기존의 Postgresql에 대한 Datasource는 아래와 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<bean id="egov.propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/egovframework/egovProps/globals.properties</value>
</list>
</property>
</bean>
<alias name="dataSource-postgresql" alias="dataSource"/>
<!-- JDBC-PostgreSQL -->
<bean id="dataSource-postgresql" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${Globals.DriverClassName}" />
<property name="url" value="${Globals.Url}" />
<property name="username" value="${Globals.UserName}" />
<property name="password" value="${Globals.Password}" />
</bean>
|
cs |
여기서 이제 Tibero DB에 대한 Datasource를 아래와 같이 추가해 줍니다. 물론 globalglobals.properties파일에 추가하고자 하는 DB정보를 추가해줍니다. 저는 Tibero를 붙여서 사용했습니다.
1
2
3
4
5
6
7
8
9
10
11
|
<alias name="dataSource-tibero" alias="tibero.dataSource"/>
<!-- tibero -->
<bean id="dataSource-tibero" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${Globals.Tibero.DriverClassName}"/>
<property name="url" value="${Globals.Tibero.Url}" />
<property name="username" value="${Globals.Tibero.UserName}"/>
<property name="password" value="${Globals.Tibero.Password}"/>
<property name="validationQuery" value="select 1 from dual" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
</bean>
|
cs |
context-mapper.xml 설정 - SqlSessionFactoryBean, SqlSessionTemplate 추가
파일의 위치는 위의 context-datasource.xml의 위치와 같습니다.
위의 Package Presentaion사진을 참고하세요.
기존의 postgresql의 sqlsession bean 설정은 아래와 같습니다.
postgresql을 사용하는 쿼리 문은 <property name="mapperLocations" value="classpath:/egovframework/sqlmap/mappers/**/*.xml" />
여기에 작성되어 있습니다.
1
2
3
4
5
6
7
8
9
10
|
<!-- SqlSession setup for MyBatis Database Layer -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/egovframework/sqlmap/config/sql-mapper-config.xml" />
<property name="mapperLocations" value="classpath:/egovframework/sqlmap/mappers/**/*.xml" />
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSession"/>
</bean>
|
cs |
여기에 추가하고자 하는 DB(저는 Tibero DB)의 sqlsession id를 새로 하나 지정해서 bean등록을 아래와 같이 추가합니다.
저는 sqlSession2, sqlSessionTemplate2라고 지정했습니다.
Tibero DB를 사용하는 쿼리문을 작성할 디렉터리를 하나 새로 만들어서 mapperLocations의 value에 경로를 적습니다. (Package Presentaion사진을 참고) 와일드카드 문자는 원하시는 것을 사용해도 됩니다.
1
2
3
4
5
6
7
8
9
|
<!-- Tibero SqlSession -->
<bean id="sqlSession2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="tibero.dataSource" />
<property name="mapperLocations" value="classpath:/egovframework/sqlmap/mappers/disaster/tibero/*.xml" />
</bean>
<bean id="sqlSessionTemplate2" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSession2"/>
</bean>
|
cs |
AbstractDAO class 추가
이전까지는 egovframework.com.cmm.service.impl 패키지의 EgovComAbstractDAO를 사용해서 쿼리문을 동작시켰을 겁니다. 추가할 DB에는 새로운 Abstract Calss를 추가하여 추가할 DB 전용 추상 클래스를 만들어줍니다.
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
/* TiberoAbstractDAO */
package egovframework.wini.disaster.service.impl;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
public abstract class TiberoAbstractDAO extends SqlSessionDaoSupport{
/**
* Annotation 형식으로 sqlSession(SqlSessionFactoryBean)을 받아와
* 이를 super(SqlSessionDaoSupport)의 setSqlSessionFactory 메서드를 호출하여 설정해 준다.
* <p>
* SqlSessionTemplate이 지정된 경우된 경우 이 SqlSessionFactory가 무시된다. (Batch 처리를 위해서는 SqlSessionTemplate가 필요)
* </p>
*
* @param sqlSession SqlSessionFactory로 MyBatis와의 연계를 위한 기본 클래스
*/
@Resource(name = "sqlSession2")
public void setSqlSessionFactory(SqlSessionFactory sqlSession) {
super.setSqlSessionFactory(sqlSession);
}
/**
* 입력 처리 SQL mapping 을 실행한다.
*
* @param queryId - 입력 처리 SQL mapping 쿼리 ID
*
* @return DBMS가 지원하는 경우 insert 적용 결과 count
*/
public int insert(String queryId) {
return getSqlSession().insert(queryId);
}
/**
* 입력 처리 SQL mapping 을 실행한다.
*
* @param queryId - 입력 처리 SQL mapping 쿼리 ID
* @param parameterObject - 입력 처리 SQL mapping 입력 데이터를 세팅한 파라메터 객체(보통 VO 또는 Map)
*
* @return DBMS가 지원하는 경우 insert 적용 결과 count
*/
public int insert(String queryId, Object parameterObject) {
return getSqlSession().insert(queryId, parameterObject);
}
/**
* 수정 처리 SQL mapping 을 실행한다.
*
* @param queryId - 수정 처리 SQL mapping 쿼리 ID
*
* @return DBMS가 지원하는 경우 update 적용 결과 count
*/
public int update(String queryId) {
return getSqlSession().update(queryId);
}
/**
* 수정 처리 SQL mapping 을 실행한다.
*
* @param queryId - 수정 처리 SQL mapping 쿼리 ID
* @param parameterObject - 수정 처리 SQL mapping 입력 데이터(key 조건 및 변경 데이터)를 세팅한 파라메터 객체(보통 VO 또는 Map)
*
* @return DBMS가 지원하는 경우 update 적용 결과 count
*/
public int update(String queryId, Object parameterObject) {
return getSqlSession().update(queryId, parameterObject);
}
/**
* 삭제 처리 SQL mapping 을 실행한다.
*
* @param queryId - 삭제 처리 SQL mapping 쿼리 ID
*
* @return DBMS가 지원하는 경우 delete 적용 결과 count
*/
public int delete(String queryId) {
return getSqlSession().delete(queryId);
}
/**
* 삭제 처리 SQL mapping 을 실행한다.
*
* @param queryId - 삭제 처리 SQL mapping 쿼리 ID
* @param parameterObject - 삭제 처리 SQL mapping 입력 데이터(일반적으로 key 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
*
* @return DBMS가 지원하는 경우 delete 적용 결과 count
*/
public int delete(String queryId, Object parameterObject) {
return getSqlSession().delete(queryId, parameterObject);
}
//CHECKSTYLE:OFF
/**
* 명명규칙에 맞춰 selectOne()로 변경한다.
* @deprecated select() 메소드로 대체
*
* @see EgovAbstractMapper.selectOne()
*/
//CHECKSTYLE:ON
@Deprecated
public Object selectByPk(String queryId, Object parameterObject) {
return getSqlSession().selectOne(queryId, parameterObject);
}
/**
* 단건조회 처리 SQL mapping 을 실행한다.
*
* @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
*
* @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)
*/
public <T> T selectOne(String queryId) {
return getSqlSession().selectOne(queryId);
}
/**
* 단건조회 처리 SQL mapping 을 실행한다.
*
* @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 단건 조회 처리 SQL mapping 입력 데이터(key)를 세팅한 파라메터 객체(보통 VO 또는 Map)
*
* @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)
*/
public <T> T selectOne(String queryId, Object parameterObject) {
return getSqlSession().selectOne(queryId, parameterObject);
}
/**
* 결과 목록을 Map 을 변환한다.
* 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
*
* @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
* @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
*
* @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
*/
public <K, V> Map<K, V> selectMap(String queryId, String mapKey) {
return getSqlSession().selectMap(queryId, mapKey);
}
/**
* 결과 목록을 Map 을 변환한다.
* 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
*
* @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
* @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
*
* @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
*/
public <K, V> Map<K, V> selectMap(String queryId, Object parameterObject, String mapKey) {
return getSqlSession().selectMap(queryId, parameterObject, mapKey);
}
/**
* 결과 목록을 Map 을 변환한다.
* 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
*
* @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
* @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
* @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함
*
* @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
*/
public <K, V> Map<K, V> selectMap(String queryId, Object parameterObject, String mapKey, RowBounds rowBounds) {
return getSqlSession().selectMap(queryId, parameterObject, mapKey, rowBounds);
}
//CHECKSTYLE:OFF
/**
* 명명규칙에 맞춰 selectList()로 변경한다.
*
* @see EgovAbstractMapper.selectList()
* @deprecated List<?> 메소드로 대체
*/
//CHECKSTYLE:ON
@Deprecated
public List<?> list(String queryId, Object parameterObject) {
return getSqlSession().selectList(queryId, parameterObject);
}
/**
* 리스트 조회 처리 SQL mapping 을 실행한다.
*
* @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
*
* @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
*/
public <E> List<E> selectList(String queryId) {
return getSqlSession().selectList(queryId);
}
/**
* 리스트 조회 처리 SQL mapping 을 실행한다.
*
* @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
*
* @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
*/
public <E> List<E> selectList(String queryId, Object parameterObject) {
return getSqlSession().selectList(queryId, parameterObject);
}
/**
* 리스트 조회 처리 SQL mapping 을 실행한다.
*
* @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
* @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함
*
* @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
*/
public <E> List<E> selectList(String queryId, Object parameterObject, RowBounds rowBounds) {
return getSqlSession().selectList(queryId, parameterObject, rowBounds);
}
/**
* 부분 범위 리스트 조회 처리 SQL mapping 을 실행한다.
* (부분 범위 - pageIndex 와 pageSize 기반으로 현재 부분 범위 조회를 위한 skipResults, maxResults 를 계산하여 ibatis 호출)
*
* @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
* @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
* @param pageIndex - 현재 페이지 번호
* @param pageSize - 한 페이지 조회 수(pageSize)
*
* @return 부분 범위 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 부분 범위 결과 객체(보통 VO 또는 Map) List
*/
public List<?> listWithPaging(String queryId, Object parameterObject, int pageIndex, int pageSize) {
int skipResults = pageIndex * pageSize;
//int maxResults = (pageIndex * pageSize) + pageSize;
RowBounds rowBounds = new RowBounds(skipResults, pageSize);
return getSqlSession().selectList(queryId, parameterObject, rowBounds);
}
/**
* SQL 조회 결과를 ResultHandler를 이용해서 출력한다.
* ResultHandler를 상속해 구현한 커스텀 핸들러의 handleResult() 메서드에 따라 실행된다.
*
* @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
* @param handler - 조회 결과를 제어하기 위해 구현한 ResultHandler
* @return
*
* @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
*/
public void listToOutUsingResultHandler(String queryId, ResultHandler handler) {
getSqlSession().select(queryId, handler);
}
}
|
cs |
원하시는 패키지 아래에 TiberoAbstractDAO 추상클래스를 생성 하시고 SqlSessionDaoSupport를 상속받은 뒤에 그대로 복붙 하여 사용하셔도 무관 합니다.
단, 23번 라인의 @Resource(name = "sqlSession2")을 잊지 말고 꼭 context-mapper.xml에 설정했던 SqlSessionFactoryBean의 id와 동일하게 적어줘야 됩니다.
이제 DAO클래스 하나를 생성하고 Service단에서 DAO를 호출한 뒤 DAO에서 TiberoAbstractDAO를 상속받고 추상 클래스에 정의된 메서드들을 이용하여 쿼리를 타게 될 겁니다.
예시 Controller , Service, DAO
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
|
/* Controller */
@Controller
public class NdmsRegisterController {
/* NDMS Service */
@Resource(name = "NdmsRegisterService")
private NdmsRegisterService service;
@RequestMapping("/ndms/ndmsRegisterDisaster.do")
public String registerDisaster(HttpServletRequest request, Model model){
List<Map<String,Object>> result = null;
try {
result = service.test();
model.addAttribute("test",result);
} catch (Exception e) {
e.printStackTrace();
}
return "ndmsA/ndmsRegisterDisaster";
}
@RequestMapping("/ndms/test.do")
public String test(){
return "ndms/test";
}
}
/* Service */
@Service("NdmsRegisterService")
public class NdmsRegisterServiceImpl implements NdmsRegisterService{
@Autowired
private NdmsRegisterDAO dao;
@Override
public List<Map<String, Object>> test() {
List<Map<String,Object>> result = null;
try {
result = dao.test();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
/* DAO */
@Repository("NdmsDAO")
public class NdmsRegisterDAO extends TiberoAbstractDAO{
public List<Map<String, Object>> test() {
return selectList("NdmsDAO.test");
}
}
|
cs |
Controller에서 Service를 전역 변수로 설정해놓고 사용하는데
@Resource(name = "NdmsRegisterService") 이렇게 @Resource어노테이션을 사용하고 값을 Service명으로 꼭 입력해주어야 합니다.
이 예시는 말 그대로 예시 일분 그대로 복붙 하지 마시고 본인의 상황에 맡게 클래스를 생성한 후 사용하시면 됩니다. 물론 Service와 DAO는 interface가 있고, Implement class를 따로 만드는 게 좋습니다.
SQL.xml 에서는 mapper namespace명을 DAO클래스에 명시한 대로 하면 됩니다.
<mapper namespace="NdmsDAO"> 이런 식으로 요.
이상으로 하나의 프로젝트에 두 개의 DB를 붙이는 방법을 적어봤습니다.
다들 즐겁지 않은 즐거운 코딩 하세요
'WEB > Spring' 카테고리의 다른 글
[Spring]게시글 상세보기에서 댓글(대댓글) 출력 로직 정리 (4) | 2021.05.04 |
---|---|
[Spring]파일 업로드의 구현(1개의 파일) (1) | 2020.12.04 |
[Spring]게시판 글 상세보기에서 '좋아요' 처리 로직 정리 (12) | 2020.09.14 |
[Spring]페이징 처리 EgovFramework Paginationinfo 사용하기( JSP, Controller) (3) | 2020.07.21 |
[Spring]페이징 처리 EgovFramework Paginationinfo 사용하기( 설정) (3) | 2020.07.21 |