Package play.db.jpa

Source Code of play.db.jpa.JPAConfig

package play.db.jpa;

import java.lang.reflect.Modifier;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.hibernate.ejb.Ejb3Configuration;
import play.Invoker;
import play.Play;
import play.classloading.ApplicationClasses;
import play.exceptions.JPAException;

/**
* JPA Support for a specific JPA/DB configuration
*
* dbConfigName corresponds to properties-names in application.conf.
*
* The default DBConfig is the one configured using 'db.' in application.conf
*
* dbConfigName = 'other' is configured like this:
*
* db_other = mem
* db_other.user = batman
*
*
* A particular JPAConfig-instance uses the DBConfig with the same configName
*/

public class JPAConfig {
    private final String configName;
    private EntityManagerFactory entityManagerFactory = null;
    private ThreadLocal<JPAContext> local = new ThreadLocal<JPAContext>();
    public final JPQL jpql;

    protected JPAConfig(Ejb3Configuration cfg, String configName) {
        this.configName = configName;
        invokeJPAConfigurationExtensions(cfg, configName);
        entityManagerFactory = cfg.buildEntityManagerFactory();
        jpql = new JPQL(this);
    }

    public String getConfigName() {
        return configName;
    }

    protected void close() {
        if (isEnabled()) {
            try {
                entityManagerFactory.close();
            } catch (Exception e) {
                // ignore it - we don't care if it failed..
            }
            entityManagerFactory = null;
        }
    }

    /**
     * @return true if an entityManagerFactory has started
     */
    public boolean isEnabled() {
        return entityManagerFactory != null;
    }

    /*
     * Build a new entityManager.
     * (In most case you want to use the local entityManager with em)
     */
    public EntityManager newEntityManager() {
        return entityManagerFactory.createEntityManager();
    }

    /**
     * gets the active or create new
     * @return the active JPAContext bound to current thread
     */
    public JPAContext getJPAContext() {
        return getJPAContext(null);
    }


    /**
     * gets the active or create new. manualReadOnly is only used if we're create new context
     * @param manualReadOnly is not null, this value is used instead of value from @Transactional.readOnly
     * @return the active JPAContext bound to current thread
     */
    protected JPAContext getJPAContext(Boolean manualReadOnly) {
        JPAContext context = local.get();
        if ( context == null) {
            // throw new JPAException("The JPAContext is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the @javax.persistence.Entity annotation are found in the application.");

            // This is the first time someone tries to use JPA in this thread.
            // we must initialize it

            if(Invoker.InvocationContext.current().getAnnotation(NoTransaction.class) != null ) {
                //Called method or class is annotated with @NoTransaction telling us that
                //we should not start a transaction
                throw new JPAException("Cannot create JPAContext due to @NoTransaction");
            }

            boolean readOnly = false;
            if (manualReadOnly!=null) {
                readOnly = manualReadOnly;
            } else {
                Transactional tx = Invoker.InvocationContext.current().getAnnotation(Transactional.class);
                if (tx != null) {
                    readOnly = tx.readOnly();
                }
            }
            context = new JPAContext(this, readOnly, JPAPlugin.autoTxs);

            local.set(context);
        }
        return context;
    }

    protected void clearJPAContext() {
        JPAContext context = local.get();
        if (context != null) {
            try {
                context.close();
            } catch(Exception e) {
                // Let's it fail
            }
            local.remove();
        }
    }

    /**
     * @return true if JPA is enabled in current thread
     */
    public boolean threadHasJPAContext() {
        return local.get() != null;
    }

    public boolean isInsideTransaction() {
        if (!threadHasJPAContext()) {
            return false;
        }
        return getJPAContext().isInsideTransaction();
    }

    /**
     * Looks up all {@link JPAConfigurationExtension} implementations and applies them to the JPA configuration.
     *
     * @param cfg the {@link} Ejb3Configuration for this {@link JPAConfig}
     * @param configName the name of the db configuration
     */
    protected void invokeJPAConfigurationExtensions(Ejb3Configuration cfg, String configName) {
        for(ApplicationClasses.ApplicationClass c : Play.classes.getAssignableClasses(JPAConfigurationExtension.class)) {
            if(!Modifier.isAbstract(c.getClass().getModifiers())) {
                JPAConfigurationExtension extension = null;
                try {
                    extension = (JPAConfigurationExtension) c.javaClass.newInstance();
                } catch (Throwable t) {
                    throw new JPAException(String.format("Could not instantiate JPAConfigurationExtension '%s'", c.javaClass.getName()), t);
                }
                if(extension.getConfigurationName() == null || extension.getConfigurationName().equals(configName)) {
                    extension.configure(cfg);
                }
            }
        }
    }
}
TOP

Related Classes of play.db.jpa.JPAConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.