Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- RefreshableSqlSessionFactoryBean
- ORA-01005
- 나주
- 요리
- Responsively app
- JavaScript
- AbstractViewe
- 양동점
- SVN사용방법
- 은혜침구
- 정민이초밥
- 루키초밥
- css
- 광주
- Jsp Pagination
- Eclipse
- 반응형앱
- ORA-01745
- Oracle
- ORA-01756
- 맛집
- egov
- 문방구과자
- mybatis
- Java
- 배딩작업
- docker
- 카페
- 디카페인
- ORA-00909
Archives
- Today
- Total
gnusraun
Egov RefreshableSqlSessionFactoryBean 서버 재시작 없이 XML 반영 본문
728x90
TOMCAT 서버 기준 XML 쿼리를 수정하면 서버를 재시작해야 한다.
이러한 번거로운 작업을 줄이기 위해 서버 재시작 없이도 XML 쿼리를 반영하는 RefreshableSqlSessionFactoryBean 사용한다.
:: RefreshableSqlSessionFactoryBean.java
package egovframework.example.cmmn.config;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.io.Resource;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(RefreshableSqlSessionFactoryBean.class);
private SqlSessionFactory proxy;
private int interval = 500;
private Timer timer;
private TimerTask task;
private Resource[] mapperLocations;
private boolean running = false;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public void setMapperLocations(Resource[] mapperLocations) {
super.setMapperLocations(mapperLocations);
this.mapperLocations = mapperLocations;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void refresh() throws Exception {
if(logger.isInfoEnabled()) {
logger.info("> Refresh SqlMapper");
logger.info("======================================================================================");
}
w.lock();
try {
super.afterPropertiesSet();
} finally {
w.unlock();
}
}
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
setRefreshable();
}
private void setRefreshable() {
proxy = (SqlSessionFactory) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSessionFactory.class},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// log.debug("method.getName() : " + method.getName());
return method.invoke(getParentObject(), args);
}
});
task = new TimerTask() {
private Map<Resource, Long> map = new HashMap<Resource, Long>();
public void run() {
if(isModified()) {
try {
refresh();
} catch(Exception e) {
logger.error("caught exception", e);
}
}
}
private boolean isModified() {
boolean retVal = false;
if(mapperLocations != null) {
for(int i = 0; i < mapperLocations.length; i++) {
Resource mappingLocation = mapperLocations[i];
retVal |= findModifiedResource(mappingLocation);
}
}
return retVal;
}
private boolean findModifiedResource(Resource resource) {
boolean retVal = false;
List<String> modifiedResources = new ArrayList<String>();
try {
long modified = resource.lastModified();
if(map.containsKey(resource)) {
long lastModified = ((Long) map.get(resource)) .longValue();
if(lastModified != modified) {
map.put(resource, new Long(modified));
//modifiedResources.add(resource.getDescription()); // 전체경로
modifiedResources.add(resource.getFilename()); // 파일명
retVal = true;
}
} else {
map.put(resource, new Long(modified));
}
} catch (IOException e) {
logger.error("caught exception", e);
}
if(retVal) {
if(logger.isInfoEnabled()) {
logger.info("======================================================================================");
logger.info("> Update File name : " + modifiedResources);
}
}
return retVal;
}
};
timer = new Timer(true);
resetInterval();
}
private Object getParentObject() throws Exception {
r.lock();
try {
return super.getObject();
} finally {
r.unlock();
}
}
public SqlSessionFactory getObject() {
return this.proxy;
}
public Class<? extends SqlSessionFactory> getObjectType() {
return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class);
}
public boolean isSingleton() {
return true;
}
public void setCheckInterval(int ms) {
interval = ms;
if(timer != null) {
resetInterval();
}
}
private void resetInterval() {
if(running) {
timer.cancel();
running = false;
}
if(interval > 0) {
timer.schedule(task, 0, interval); running = true;
}
}
public void destroy() throws Exception {
timer.cancel();
}
}
:: context-mapper.xml
<!-- class 경로 추가 -->
<bean id="sqlSession" class="egovframework.example.cmmn.config.RefreshableSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/egovframework/sqlmap/oracle/sql-mapper-config.xml" />
<property name="mapperLocations" value="classpath:/egovframework/sqlmap/oracle/mappers/**/*.xml" />
<property name="interval" value="1000" />
</bean>
728x90
'Backend > Egov' 카테고리의 다른 글
Egov jsp 에러 페이지 표출 (0) | 2023.05.16 |
---|---|
Egov org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement (0) | 2023.05.16 |
Egov 오라클 연동 (0) | 2023.05.13 |
Egov Scheduler 설정 (0) | 2023.05.13 |
Egov Pagination 페이지 처리 (0) | 2023.05.13 |