org.grails.datastore.mapping.jpa.JpaSession.java Source code

Java tutorial

Introduction

Here is the source code for org.grails.datastore.mapping.jpa.JpaSession.java

Source

/* Copyright (C) 2011 SpringSource
 *
 * 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 org.grails.datastore.mapping.jpa;

import java.io.Serializable;
import java.util.*;

import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceException;

import org.grails.datastore.mapping.query.api.QueryableCriteria;
import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder;
import org.grails.datastore.mapping.query.jpa.JpaQueryInfo;
import org.springframework.core.convert.ConversionService;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.grails.datastore.mapping.core.AbstractAttributeStoringSession;
import org.grails.datastore.mapping.engine.EntityAccess;
import org.grails.datastore.mapping.engine.Persister;
import org.grails.datastore.mapping.jpa.query.JpaQuery;
import org.grails.datastore.mapping.model.MappingContext;
import org.grails.datastore.mapping.model.PersistentEntity;
import org.grails.datastore.mapping.query.Query;
import org.grails.datastore.mapping.transactions.Transaction;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.JpaTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * Wraps a JPA EntityManager in the Datastore Session interface.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class JpaSession extends AbstractAttributeStoringSession {

    private JpaDatastore datastore;
    private JpaTemplate jpaTemplate;
    private JpaTransactionManager transactionManager;
    private FlushModeType flushMode;
    private TransactionStatus transaction;

    public JpaSession(JpaDatastore datastore, JpaTemplate jpaTemplate, JpaTransactionManager transactionManager) {
        this.jpaTemplate = jpaTemplate;
        this.datastore = datastore;
        this.transactionManager = transactionManager;
    }

    public JpaTemplate getJpaTemplate() {
        return jpaTemplate;
    }

    public Transaction beginTransaction() {
        final TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        return new JpaTransaction(transactionManager, status);
    }

    public MappingContext getMappingContext() {
        return datastore.getMappingContext();
    }

    public Serializable persist(Object o) {
        if (o == null) {
            throw new InvalidDataAccessApiUsageException("Object to persist cannot be null");
        }

        final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName());
        if (persistentEntity == null) {
            throw new InvalidDataAccessApiUsageException(
                    "Object of class [" + o.getClass().getName() + "] is not a persistent entity");
        }

        jpaTemplate.persist(o);
        return (Serializable) new EntityAccess(persistentEntity, o).getIdentifier();
    }

    public Object merge(Object o) {
        if (o == null) {
            throw new InvalidDataAccessApiUsageException("Object to merge cannot be null");
        }

        final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName());
        if (persistentEntity == null) {
            throw new InvalidDataAccessApiUsageException(
                    "Object of class [" + o.getClass().getName() + "] is not a persistent entity");
        }

        return jpaTemplate.merge(o);
    }

    public void refresh(Object o) {
        if (o == null) {
            return;
        }
        jpaTemplate.refresh(o);
    }

    public void attach(Object o) {
        if (o == null) {
            return;
        }
        jpaTemplate.merge(o);
    }

    public void flush() {
        if (hasTransaction()) {
            jpaTemplate.flush();
        }
    }

    public static boolean hasTransaction() {
        return TransactionSynchronizationManager.isActualTransactionActive()
                && !TransactionSynchronizationManager.isCurrentTransactionReadOnly();
    }

    public void clear() {
        jpaTemplate.execute(new JpaCallback<Void>() {
            public Void doInJpa(EntityManager em) throws PersistenceException {
                em.clear();
                return null;
            }
        });
    }

    public void clear(Object o) {
        // do nothing
    }

    public boolean contains(Object o) {
        return jpaTemplate.contains(o);
    }

    public void setFlushMode(FlushModeType flushMode) {
        this.flushMode = flushMode;
        jpaTemplate.setFlushEager(flushMode == FlushModeType.AUTO);
    }

    public FlushModeType getFlushMode() {
        return flushMode;
    }

    public void lock(final Object o) {
        jpaTemplate.execute(new JpaCallback<Void>() {
            public Void doInJpa(EntityManager em) throws PersistenceException {
                em.lock(o, LockModeType.WRITE);
                return null;
            }
        });
    }

    public void unlock(Object o) {
        // noop. Not supported in JPA
    }

    public List<Serializable> persist(final Iterable objects) {
        return jpaTemplate.execute(new JpaCallback<List<Serializable>>() {
            public List<Serializable> doInJpa(EntityManager em) throws PersistenceException {
                List<Serializable> identifiers = new ArrayList<Serializable>();
                for (Object object : objects) {
                    identifiers.add(persist(object));
                }
                return identifiers;
            }
        });
    }

    public <T> T retrieve(Class<T> type, Serializable key) {
        final PersistentEntity persistentEntity = getPersistentEntity(type);
        if (persistentEntity == null) {
            return null;
        }

        final ConversionService conversionService = getMappingContext().getConversionService();
        final Object id = conversionService.convert(key, persistentEntity.getIdentity().getType());
        return jpaTemplate.find(type, id);
    }

    public <T> T proxy(Class<T> type, Serializable key) {
        return jpaTemplate.getReference(type, key);
    }

    public <T> T lock(Class<T> type, Serializable key) {
        final T obj = retrieve(type, key);
        lock(obj);
        return obj;
    }

    public void delete(Iterable objects) {
        for (Object object : objects) {
            jpaTemplate.remove(object);
        }
    }

    public void delete(Object obj) {
        jpaTemplate.remove(obj);
    }

    /**
     * Deletes all objects matching the given criteria
     *
     * @param criteria The criteria
     * @return The total number of records deleted
     */
    public int deleteAll(final QueryableCriteria criteria) {
        return jpaTemplate.execute(new JpaCallback<Integer>() {
            public Integer doInJpa(EntityManager em) throws PersistenceException {
                JpaQueryBuilder builder = new JpaQueryBuilder(criteria);
                JpaQueryInfo jpaQueryInfo = builder.buildDelete();
                javax.persistence.Query query = em.createQuery(jpaQueryInfo.getQuery());
                List parameters = jpaQueryInfo.getParameters();
                if (parameters != null) {
                    for (int i = 0, count = parameters.size(); i < count; i++) {
                        query.setParameter(i + 1, parameters.get(i));
                    }
                }
                return query.executeUpdate();
            }
        });
    }

    /**
     * Updates all objects matching the given criteria and property values
     *
     * @param criteria   The criteria
     * @param properties The properties
     * @return The total number of records updated
     */
    public int updateAll(final QueryableCriteria criteria, final Map<String, Object> properties) {
        return jpaTemplate.execute(new JpaCallback<Integer>() {
            public Integer doInJpa(EntityManager em) throws PersistenceException {
                JpaQueryBuilder builder = new JpaQueryBuilder(criteria);
                JpaQueryInfo jpaQueryInfo = builder.buildUpdate(properties);
                javax.persistence.Query query = em.createQuery(jpaQueryInfo.getQuery());
                List parameters = jpaQueryInfo.getParameters();
                if (parameters != null) {
                    for (int i = 0, count = parameters.size(); i < count; i++) {
                        query.setParameter(i + 1, parameters.get(i));
                    }
                }
                return query.executeUpdate();
            }
        });
    }

    public List retrieveAll(Class type, Iterable keys) {
        if (keys instanceof List) {
            return retrieveAll(getPersistentEntity(type), (List) keys);
        }
        List identifierList = new ArrayList();
        for (Object key : keys) {
            identifierList.add(key);
        }
        return retrieveAll(getPersistentEntity(type), identifierList);
    }

    public PersistentEntity getPersistentEntity(Class type) {
        return getMappingContext().getPersistentEntity(type.getName());
    }

    public List retrieveAll(Class type, Serializable... keys) {
        if (type == null) {
            return Collections.emptyList();
        }

        final PersistentEntity persistentEntity = getPersistentEntity(type);
        if (persistentEntity == null) {
            return Collections.emptyList();
        }

        final List<Serializable> identifiers = Arrays.asList(keys);
        return retrieveAll(persistentEntity, identifiers);
    }

    public List retrieveAll(final PersistentEntity persistentEntity, final List<Serializable> identifiers) {
        return createQuery(persistentEntity.getJavaClass())
                .in(persistentEntity.getIdentity().getName(), identifiers).list();
    }

    public Query createQuery(Class type) {
        return new JpaQuery(this, getPersistentEntity(type));
    }

    public Object getNativeInterface() {
        return jpaTemplate;
    }

    public Persister getPersister(Object o) {
        return null;
    }

    public Transaction getTransaction() {
        if (transaction == null) {
            return null;
        }
        return new JpaTransaction(transactionManager, transaction);
    }

    public JpaDatastore getDatastore() {
        return datastore;
    }

    public void setTransactionStatus(TransactionStatus transaction) {
        this.transaction = transaction;
    }

    public boolean isDirty(Object instance) {
        // TODO
        return false;
    }
}