2013년 7월 8일 월요일

MySql Master Slave Replication 에서 Hibernate 사용하기 2

MySQL Master Slave Replication 에서 Hibernate 사용하기 에서 만든 ConnectionInterceptor 는 Custom Annotation을 사용하여, 부가적인 노가다가 필요했습니다.

보통 Spring 을 사용하니 Spring 의 @Transactional 을 이용하여, readOnly 속성에 따른 작업을 수행하면 될 것입니다.
제가 Spring Aop 에 초보라 좀 찾아보는데 시간이 걸리네요...

어쨌든 구글링을 통해 방법을 찾아서 개선된 ConnectionInterceptor 를 올립니다.

@Transactional을 사용하는 ConnectionInterceptor.java

/**
* 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 에 접속하게하고, 아니라면 그대로 실행하도록 합니다.

댓글 없음: