보통 Spring 을 사용하니 Spring 의 @Transactional 을 이용하여, readOnly 속성에 따른 작업을 수행하면 될 것입니다.
제가 Spring Aop 에 초보라 좀 찾아보는데 시간이 걸리네요...
어쨌든 구글링을 통해 방법을 찾아서 개선된 ConnectionInterceptor 를 올립니다.
@Transactional을 사용하는 ConnectionInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* MySQL Replication 환경 (Master-Slave)에서 | |
* {@link org.springframework.transaction.annotation.Transactional#readOnly()} 이 true로 정의된 Method에 대해서는 | |
* Slave 서버로 접속하기 위해, {@link java.sql.Connection#isReadOnly()}의 속성을 true로 변경하여 작업을 수행하도록 합니다. | |
* | |
* @author 배성혁 sunghyouk.bae@gmail.com | |
* @since 13. 7. 5. 오후 11:07 | |
*/ | |
@Aspect | |
@Component | |
public class ConnectionInterceptor { | |
private static final Logger log = LoggerFactory.getLogger(ConnectionInterceptor.class); | |
private static final boolean isTraceEnabled = log.isTraceEnabled(); | |
@Autowired | |
private SessionFactory sessionFactory; | |
@Around(value = "@annotation(transactional)", argNames = "transactional") | |
public Object proceed(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable { | |
if (!transactional.readOnly()) { | |
return pjp.proceed(); | |
} else { | |
log.debug("읽기전용 작업을 수행하기 위해 현 connection를 readonly로 설정합니다..."); | |
SessionImpl session = (SessionImpl) sessionFactory.getCurrentSession(); | |
Connection connection = session.connection(); | |
boolean autoCommit = connection.getAutoCommit(); | |
boolean readOnly = connection.isReadOnly(); | |
try { | |
// MySQL SLAVE 서버에 접속하기 위해 Connection 속성을 설정합니다. | |
connection.setAutoCommit(false); | |
connection.setReadOnly(true); | |
// @ReadOnlyConnection이 선언된 메소드를 실행합니다. | |
return pjp.proceed(); | |
} finally { | |
connection.setAutoCommit(autoCommit); | |
connection.setReadOnly(readOnly); | |
log.debug("읽기전용 작업을 수행하고, connection의 원래 설정으로 재설정했습니다."); | |
} | |
} | |
} | |
} |
보시다시피 @Transactional 이 정의된 메소드에 readOnly=true 인 경우에는 Slave 에 접속하게하고, 아니라면 그대로 실행하도록 합니다.
댓글 없음:
댓글 쓰기