/* * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package kr.debop4j.data.mysql; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.hibernate.SessionFactory; import org.hibernate.internal.SessionImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.sql.Connection; /** * MySQL Replication 환경 (Master-Slave)에서 {@link ReadOnlyConnection} 이 정의된 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( "@annotation(ReadOnlyConnection)" ) public Object proceed(ProceedingJoinPoint pjp) throws Throwable { 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의 원래 설정으로 재설정했습니다."); } } }