kr.debop4j.data.hibernate.unitofwork.UnitOfWorks.java Source code

Java tutorial

Introduction

Here is the source code for kr.debop4j.data.hibernate.unitofwork.UnitOfWorks.java

Source

/*
 * 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;
    }
}