Java tutorial
/* * 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.unitofwork; import kr.debop4j.core.AutoCloseableAction; import kr.debop4j.core.Local; import lombok.extern.slf4j.Slf4j; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.concurrent.ThreadSafe; import static kr.debop4j.core.Guard.shouldNotBeNull; /** * Unit of Work ? Static ?. * * @author ? ( sunghyouk.bae@gmail.com ) * @since 12. 12. 18 */ @Component @Slf4j @ThreadSafe public final class UnitOfWorks { private UnitOfWorks() { } static { log.info("UnitOfWorks ? ??."); } private static final String UNIT_OF_WORK_NOT_STARTED = "UnitOfWorks ? . ? UnitOfWorks.start() ."; private static volatile IUnitOfWork globalNonThreadSafeUnitOfWork; private static volatile IUnitOfWorkFactory unitOfWorkFactory; /** UnitOfWork ? ? ?. */ public static synchronized boolean isStarted() { return globalNonThreadSafeUnitOfWork != null || Local.get(IUnitOfWork.CURRENT_UNIT_OF_WORK_KEY) != null; } /** ? {@link IUnitOfWork}? ? ({@link UnitOfWorkAdapter} . */ public static synchronized IUnitOfWork getCurrent() { if (!isStarted()) throw new HibernateException(UNIT_OF_WORK_NOT_STARTED); if (globalNonThreadSafeUnitOfWork != null) return globalNonThreadSafeUnitOfWork; return Local.get(IUnitOfWork.CURRENT_UNIT_OF_WORK_KEY, IUnitOfWork.class); } /** * Gets current session factory. * * @return the current session factory */ public static synchronized SessionFactory getCurrentSessionFactory() { return getUnitOfWorkFactory().getSessionFactory(); } /** * Gets current session. * * @return the current session */ public static synchronized Session getCurrentSession() { return getUnitOfWorkFactory().getCurrentSession(); } /** * Gets unit of work factory. * * @return {@link IUnitOfWorkFactory} instance. */ public static synchronized IUnitOfWorkFactory getUnitOfWorkFactory() { if (unitOfWorkFactory == null) throw new RuntimeException( "Spring ? UnitOfWorks ComponentScan? ."); return unitOfWorkFactory; } /** * Spring {@link IUnitOfWorkFactory} injection ? .<p/> * : http://debop.blogspot.kr/2013/05/spring-framework-static-field-injection.html * * @param factory {@link IUnitOfWorkFactory} instance. */ @Autowired public void injectUnitOfWorkFactory(IUnitOfWorkFactory factory) { log.info("Spring? UnitOfWorkFactory ??. unitOfWorkFactory=[{}]", factory); unitOfWorkFactory = factory; } /** * Sets unit ozf work factory. * * @param factory the factory */ public static synchronized void setUnitOfWorkFactory(IUnitOfWorkFactory factory) { log.info("UnitOfWorkFactory . unitOfWorkFactory=[{}]", factory); unitOfWorkFactory = factory; } /** * Set current unit of work. * * @param unitOfWork the unit of work */ public static void setCurrent(IUnitOfWork unitOfWork) { if (log.isDebugEnabled()) log.debug(" Thread Context? UnitOfWork ? . unitOfWork=[{}]", unitOfWork); Local.put(IUnitOfWork.CURRENT_UNIT_OF_WORK_KEY, unitOfWork); } /** * Register global unit of work. * * @param globalUnitOfWork the global unit of work * @return the auto closeable action */ public static synchronized AutoCloseableAction registerGlobalUnitOfWork(IUnitOfWork globalUnitOfWork) { if (log.isDebugEnabled()) log.debug(" IUnitOfWork . globalUnitOfWork=[{}]", globalUnitOfWork); globalNonThreadSafeUnitOfWork = globalUnitOfWork; return new AutoCloseableAction(new Runnable() { @Override public void run() { globalNonThreadSafeUnitOfWork = null; } }); } /** * Start new unit of work. * * @return {@link IUnitOfWork} instance. */ public static synchronized IUnitOfWork start() { return start(null, UnitOfWorkNestingOptions.ReturnExistingOrCreateUnitOfWork); } /** * Start new unit of work. * * @param nestingOptions ? {@link UnitOfWorkNestingOptions} * @return {@link IUnitOfWork} instance. */ public static synchronized IUnitOfWork start(UnitOfWorkNestingOptions nestingOptions) { return start(null, nestingOptions); } /** * Start new unit of work. * * @param sessionFactory {@link SessionFactory} instance. * @return {@link IUnitOfWork} instance. */ public static synchronized IUnitOfWork start(SessionFactory sessionFactory) { return start(sessionFactory, UnitOfWorkNestingOptions.ReturnExistingOrCreateUnitOfWork); } /** * Start new unit of work. * * @param sessionFactory {@link SessionFactory} instance. * @param nestingOptions ? {@link UnitOfWorkNestingOptions} * @return {@link IUnitOfWork} instance. */ public static synchronized IUnitOfWork start(SessionFactory sessionFactory, UnitOfWorkNestingOptions nestingOptions) { if (log.isDebugEnabled()) log.debug(" UnitOfWork ... sessionFactory=[{}], nestingOptions=[{}]", sessionFactory, nestingOptions); if (globalNonThreadSafeUnitOfWork != null) return globalNonThreadSafeUnitOfWork; IUnitOfWorkImplementor existing = Local.get(IUnitOfWork.CURRENT_UNIT_OF_WORK_KEY, IUnitOfWorkImplementor.class); boolean useExisting = existing != null && nestingOptions == UnitOfWorkNestingOptions.ReturnExistingOrCreateUnitOfWork; if (useExisting) { log.trace( " IUnitOfWork , ?, IUnitOfWork ? . =[{}]", existing.getUsage()); existing.increseUsage(); return existing; } log.trace(" IUnitOfWorkFactory IUnitOfWork ?..."); if (existing != null && sessionFactory == null) { sessionFactory = existing.getSession().getSessionFactory(); } else if (existing == null) { sessionFactory = getCurrentSessionFactory(); } setCurrent(getUnitOfWorkFactory().create(sessionFactory, existing)); if (log.isDebugEnabled()) log.debug(" IUnitOfWork . sessionFactory=[{}]", sessionFactory); return getCurrent(); } /** ? UnitOfWork . */ public static synchronized void stop() { stop(false); } /** * ? UnitOfWork . * * @param needFlushing Session? ?? ? flushing ? */ public static synchronized void stop(boolean needFlushing) { log.trace(" ? UnitOfWork ... needFlushing=[{}]", needFlushing); if (isStarted() && getCurrent() != null) { if (needFlushing) { try { log.trace(" UnitOfWork? Session? flushing ? ..."); getCurrent().flushSession(); log.trace(" UnitOfWork? Session? flushing ? ..."); } catch (Exception ignored) { log.error("UnitOfWork? Session? Flushing ?.", ignored); } } getCurrent().close(); } setCurrent(null); log.debug(" ? UnitOfWork ."); } /** * UnitOfWork ? runnable? . * * @param runnable */ public static void run(Runnable runnable) { shouldNotBeNull(runnable, "runnable"); try (IUnitOfWork unitOfWork = start()) { runnable.run(); } } /** * UnitOfWork ? runnable? . * * @param sessionFactory the session factory * @param runnable */ public static void run(SessionFactory sessionFactory, Runnable runnable) { shouldNotBeNull(runnable, "runnable"); try (IUnitOfWork unitOfWork = start(sessionFactory)) { runnable.run(); } } /** * UnitOfWork ? runnable? . * * @param options Unit of work ? * @param runnable */ public static void run(UnitOfWorkNestingOptions options, Runnable runnable) { shouldNotBeNull(runnable, "runnable"); try (IUnitOfWork unitOfWork = start(options)) { runnable.run(); } } /** * UnitOfWork ? runnable? . * * @param sessionFactory the session factory * @param options Unit of work ? * @param runnable */ public static void run(SessionFactory sessionFactory, UnitOfWorkNestingOptions options, Runnable runnable) { shouldNotBeNull(runnable, "runnable"); try (IUnitOfWork unitOfWork = start(sessionFactory, options)) { runnable.run(); } } /** * Unit of work . * * @param unitOfWork ? unit of work */ public static synchronized void closeUnitOfWork(IUnitOfWork unitOfWork) { if (log.isDebugEnabled()) log.debug( "UnitOfWork . ? IUnitOfWork ? Previous Current UnitOfWork ?."); setCurrent((unitOfWork != null) ? ((IUnitOfWorkImplementor) unitOfWork).getPrevious() : null); } /** Close unit of work factory. */ public static synchronized void closeUnitOfWorkFactory() { log.info("UnitOfWorkFactory ."); unitOfWorkFactory = null; } }