/* * 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.hibernate.forTesting; import com.google.common.base.Objects; import kr.debop4j.core.Guard; import kr.debop4j.core.spring.Springs; import kr.debop4j.core.tools.HashTool; import kr.debop4j.data.hibernate.unitofwork.IUnitOfWork; import kr.debop4j.data.hibernate.unitofwork.UnitOfWorkNestingOptions; import kr.debop4j.data.hibernate.unitofwork.UnitOfWorks; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.GenericApplicationContext; import java.util.UUID; /** * kr.debop4j.data.hibernate.forTesting.UnitOfWorkTestContextBase * * @author 배성혁 ( sunghyouk.bae@gmail.com ) * @since 13. 2. 19. */ @Slf4j public abstract class UnitOfWorkTestContextBase implements AutoCloseable { /** The Current hibernate session key. */ public final String CurrentHibernateSessionKey = UUID.randomUUID().toString(); /** The Spring context. */ protected GenericApplicationContext springContext; @Getter private Class dbConfigurationClass; @Getter private int unitOfWorkNestingLevel = -1; /** * Instantiates a new Unit of work test context base. * * @param dbConfigurationClass the db configuration class */ protected UnitOfWorkTestContextBase(Class dbConfigurationClass) { this.dbConfigurationClass = dbConfigurationClass; springContext = new AnnotationConfigApplicationContext(dbConfigurationClass); Springs.init(springContext); } /** * Gets spring context. * * @return the spring context */ public GenericApplicationContext getSpringContext() { synchronized (this) { if (springContext == null) { springContext = new AnnotationConfigApplicationContext(dbConfigurationClass); } } return springContext; } /** Create unit of work. */ public void createUnitOfWork() { Guard.shouldBe(unitOfWorkNestingLevel != 0, "중첩된 UnitOfWork를 만들려면 createNestedUnitOfWork() 메소드를 사용하세요."); if (log.isInfoEnabled()) log.info("현재 Session을 사용하여, UnitOfWork를 시작하고, Database를 설정합니다."); try { if (UnitOfWorks.isStarted()) { UnitOfWorks.stop(); UnitOfWorks.closeUnitOfWorkFactory(); } if (Springs.isNotInitialized()) Springs.init(getSpringContext()); UnitOfWorks.start(); setupDatabase(UnitOfWorks.getCurrentSession()); } finally { unitOfWorkNestingLevel = 0; } } /** * Create nested unit of work. * * @return the i unit of work */ public IUnitOfWork createNestedUnitOfWork() { Guard.shouldBe(this.unitOfWorkNestingLevel != -1, "부모 UnitOfWork가 존재하지 않습니다. 먼저 createUnitOfWork() 를 호출하세요"); try { IUnitOfWork uow = UnitOfWorks.start(UnitOfWorks.getCurrentSessionFactory(), UnitOfWorkNestingOptions.CreateNewOrNestUnitOfWork); return uow; } finally { unitOfWorkNestingLevel++; } } /** * Gets session factory. * * @return the session factory */ public SessionFactory getSessionFactory() { return Springs.getBean(SessionFactory.class); } /** * Create session. * * @return the session */ public Session createSession() { Session session = getSessionFactory().openSession(); return session; } /** * Dispose session. * * @param sessionToClose the session to close */ public void disposeSession(Session sessionToClose) { if (sessionToClose == null) return; if (log.isDebugEnabled()) log.debug("hibernate session을 close 합니다..."); sessionToClose.close(); if (log.isDebugEnabled()) log.debug("hibernate session을 close 했습니다."); } /** Dispose unit of work. */ public void disposeUnitOfWork() { try { UnitOfWorks.stop(); } finally { unitOfWorkNestingLevel--; } } /** Initialize container and unit of work factory. */ abstract public void initializeContainerAndUnitOfWorkFactory(); /** * Sets database. * * @param session the session */ public void setupDatabase(Session session) { // Nothing to do. } @Override public boolean equals(Object obj) { return (obj != null) && (obj instanceof UnitOfWorkTestContextBase) && (hashCode() == obj.hashCode()); } @Override public int hashCode() { return HashTool.compute(CurrentHibernateSessionKey); } public String toString() { return Objects.toStringHelper(this) .toString(); } @Override public void close() throws Exception { this.dbConfigurationClass = null; UnitOfWorks.stop(); if (springContext != null) { springContext.close(); springContext = null; } } // region << static methods >> /** * Create unit of work test context base. * * @param dbConfigurationClass the db configuration class * @return the unit of work test context base */ public static UnitOfWorkTestContextBase create(Class dbConfigurationClass) { return new UnitOfWorkTestContext(dbConfigurationClass); } // endregion }