Package org.jasig.portal.jpa

Source Code of org.jasig.portal.jpa.BaseJpaDao$NaturalIdQuery

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you 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 org.jasig.portal.jpa;

import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;

import org.hibernate.LockOptions;
import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionOperations;

import com.google.common.base.Function;

/**
* Base class for JPA DAOs in the portal that contains common functions
*
* @author Eric Dalquist
* @version $Revision$
*/
public abstract class BaseJpaDao implements InitializingBean, ApplicationContextAware {
    private static final String QUERY_SUFFIX = ".Query";
   
    protected final Logger logger = LoggerFactory.getLogger(getClass());
   
    private ApplicationContext applicationContext;
   
    protected abstract EntityManager getEntityManager();
   
    protected abstract TransactionOperations getTransactionOperations();
   
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    }
   
    protected final <T> ParameterExpression<T> createParameterExpression(Class<T> paramClass) {
        final EntityManager entityManager = this.getEntityManager();
        final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
        final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
       
        return criteriaBuilder.parameter(paramClass);
    }
   
    protected final <T> ParameterExpression<T> createParameterExpression(Class<T> paramClass, String name) {
        final EntityManager entityManager = this.getEntityManager();
        final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
        final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
       
        return criteriaBuilder.parameter(paramClass, name);
    }
   
    protected final <T> CriteriaQuery<T> createCriteriaQuery(Function<CriteriaBuilder, CriteriaQuery<T>> builder) {
        final EntityManager entityManager = this.getEntityManager();
        final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
        final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
       
        final CriteriaQuery<T> criteriaQuery = builder.apply(criteriaBuilder);
       
        //Do in TX so the EM gets closed correctly
        final TransactionOperations transactionOperations = this.getTransactionOperations();
        transactionOperations.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                entityManager.createQuery(criteriaQuery); //pre-compile critera query to avoid race conditions when setting aliases
            }
        });
       
        return criteriaQuery;
    }
   
    /**
     * Common logic for creating and configuring JPA queries
     *
     * @param criteriaQuery The criteria to create the query from
     */
    protected final <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
        return this.getEntityManager().createQuery(criteriaQuery);
    }

    /**
     * Common logic for creating and configuring JPA queries
     *
     * @param criteriaQuery The criteria to create the query from
     */
    protected final <T> TypedQuery<T> createCachedQuery(CriteriaQuery<T> criteriaQuery) {
        final TypedQuery<T> query = this.getEntityManager().createQuery(criteriaQuery);
        final String cacheRegion = getCacheRegionName(criteriaQuery);
        query.setHint("org.hibernate.cacheable", true);
        query.setHint("org.hibernate.cacheRegion", cacheRegion);
        return query;
    }
   
    /**
     * Utility for creating queries based on naturalId. The caller MUST be annotated with {@link OpenEntityManager} or
     * {@link Transactional} so that the Hibernate specific extensions are available.
     */
    protected final <T> NaturalIdQuery<T> createNaturalIdQuery(Class<T> entityType) {
        final EntityManager entityManager = this.getEntityManager();
        final Session session;
        try {
            session = entityManager.unwrap(Session.class);
        }
        catch (IllegalStateException e) {
            throw new IllegalStateException("The DAO Method that calls createNaturalIdQuery must be annotated with @OpenEntityManager or @Transactional", e);
        }
        final NaturalIdLoadAccess naturalIdLoadAccess = session.byNaturalId(entityType);
        return new NaturalIdQuery<T>(entityType, naturalIdLoadAccess);
    }

    /**
     * Creates the cache region name for the criteria query
     *
     * @param criteriaQuery The criteria to create the cache name for
     */
    protected final <T> String getCacheRegionName(CriteriaQuery<T> criteriaQuery) {
        final Set<Root<?>> roots = criteriaQuery.getRoots();
        final Class<?> cacheRegionType = roots.iterator().next().getJavaType();
        final String cacheRegion = cacheRegionType.getName() + QUERY_SUFFIX;
       
        if (roots.size() > 1) {
            logger.warn("Query " + criteriaQuery + " in " + this.getClass() + " has " + roots.size() + " roots. The first will be used to generated the cache region name: " + cacheRegion);
        }
        return cacheRegion;
    }
   
    /**
     * Build a query for an entity using its naturalId
     * @param <T> The entity type to return
     */
    public static final class NaturalIdQuery<T> {
        private final Class<T> type;
        private final NaturalIdLoadAccess naturalIdLoadAccess;

        public NaturalIdQuery(Class<T> type, NaturalIdLoadAccess naturalIdLoadAccess) {
            this.type = type;
            this.naturalIdLoadAccess = naturalIdLoadAccess;
        }

        /**
         * @see NaturalIdLoadAccess#with(LockOptions)
         */
        public NaturalIdQuery<T> with(LockOptions lockOptions) {
            naturalIdLoadAccess.with(lockOptions);
            return this;
        }

        /**
         * Set a naturalId parameter using the JPA2 MetaModel API
         * @see NaturalIdLoadAccess#using(String, Object)
         */
        public <P> NaturalIdQuery<T> using(Attribute<? super T, P> attribute, P value) {
            naturalIdLoadAccess.using(attribute.getName(), value);
            return this;
        }

        /**
         * @see NaturalIdLoadAccess#getReference()
         */
        public T getReference() {
            return type.cast(naturalIdLoadAccess.getReference());
        }

        /**
         * @see NaturalIdLoadAccess#load()
         */
        public T load() {
            return type.cast(naturalIdLoadAccess.load());
        }
    }
}
TOP

Related Classes of org.jasig.portal.jpa.BaseJpaDao$NaturalIdQuery

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.