org.mingle.pear.persistence.dao.impl.GenericDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.mingle.pear.persistence.dao.impl.GenericDaoImpl.java

Source

/*
 * Copyright 2012 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 org.mingle.pear.persistence.dao.impl;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.mingle.pear.persistence.Identifiable;
import org.mingle.pear.persistence.Pagination;
import org.mingle.pear.persistence.PaginationBuilder;
import org.mingle.pear.persistence.dao.GenericDao;
import org.mingle.pear.persistence.query.JqlQueryTemplate;
import org.mingle.pear.persistence.query.NamedQueryTemplate;
import org.mingle.pear.persistence.query.PageQuery;
import org.mingle.pear.persistence.query.QueryTemplate;
import org.mingle.pear.persistence.query.QueryType;
import org.mingle.pear.persistence.query.SqlQueryTemplate;
import org.mingle.pear.persistence.query.SqlResultSetMappingQueryTemplate;
import org.mingle.pear.util.BaseConstants;
import org.mingle.pear.util.QueryConstants;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * HibernateJPA
 *
 * @author mingle
 */
public class GenericDaoImpl<E extends Identifiable<ID>, ID extends Serializable> implements GenericDao<E, ID> {
    private final Class<E> persistentClass;

    @PersistenceContext(unitName = BaseConstants.PERSIST_UNIT_NAME, type = PersistenceContextType.TRANSACTION)
    protected EntityManager entityManager;

    public final EntityManager entityManager() {
        if (entityManager == null)
            throw new IllegalStateException("Entity manager has not been injected.");
        return entityManager;
    }

    @Override
    public Class<E> getPersistentClass() {
        return persistentClass;
    }

    @Override
    public String getDomainName() {
        return persistentClass.getName();
    }

    public GenericDaoImpl(final Class<E> persistentClass) {
        super();
        this.persistentClass = persistentClass;
    }

    /**
     * ??
     *
     * @param qt
     * @param clazz
     * @return
     */
    protected <R> Query createQuery(QueryTemplate qt, Class<R> clazz) {
        Query query = null;
        if (qt instanceof JqlQueryTemplate) {
            if (clazz == null) {
                query = entityManager().createQuery(qt.getQuery());
            } else {
                query = entityManager().createQuery(qt.getQuery(), clazz);
            }
        }
        if (qt instanceof NamedQueryTemplate) {
            if (clazz == null) {
                query = entityManager().createNamedQuery(qt.getQuery());
            } else {
                query = entityManager().createNamedQuery(qt.getQuery(), clazz);
            }
        }
        if (qt instanceof SqlQueryTemplate) {
            query = entityManager().createNativeQuery(qt.getQuery());
        }
        if (qt instanceof SqlResultSetMappingQueryTemplate) {
            SqlResultSetMappingQueryTemplate sqt = (SqlResultSetMappingQueryTemplate) qt;
            query = entityManager().createNativeQuery(qt.getQuery(), sqt.getSqlResultMapping());
        }
        // ?
        if (qt.getParameters() != null) {
            for (Entry<String, ?> paramEntry : qt.getParameters().entrySet()) {
                query.setParameter(paramEntry.getKey(), paramEntry.getValue());
            }
        }
        // 
        if (qt.isCachable()) {
            query.setHint("org.hibernate.cacheable", true);
            if (StringUtils.isNotBlank(qt.getCacheRegion())) {
                query.setHint("org.hibernate.cacheRegion", qt.getCacheRegion());
            } else {
                query.setHint("org.hibernate.cacheRegion", clazz.getName());
            }
        }
        // 
        query.setFirstResult(qt.getFirstResult());
        query.setMaxResults(qt.getMaxResults());
        return query;
    }

    @Override
    @Transactional
    public int execute(QueryTemplate qt) {
        Preconditions.checkArgument(!(qt instanceof SqlResultSetMappingQueryTemplate),
                "SqlResultMappingQueryTemplate can't execute update");
        return createQuery(qt, null).executeUpdate();
    }

    @Override
    @Transactional(readOnly = true)
    public List<Object[]> find(QueryTemplate qt) {
        Preconditions.checkArgument(!(qt instanceof SqlResultSetMappingQueryTemplate),
                "SqlResultMappingQueryTemplate can't return object[]");
        Query query = createQuery(qt, Object[].class);
        // ?
        @SuppressWarnings("unchecked")
        List<Object> results = query.getResultList();
        // 
        List<Object[]> returnVals = Lists.newArrayListWithCapacity(results.size());
        // ?List<Object[]>?
        for (Object row : results) {
            if (row.getClass().isArray()) {
                returnVals.add((Object[]) row);
            } else {
                // ?
                returnVals.add(new Object[] { row });
            }
        }
        return returnVals;
    }

    @Override
    @Transactional(readOnly = true)
    public List<Map<String, Object>> find(QueryTemplate qt, final String... fileds) {
        List<Object[]> results = find(qt);
        // ?Map
        return Lists.transform(results, new Function<Object[], Map<String, Object>>() {
            /**
             * ?Map
             */
            @Override
            public Map<String, Object> apply(Object[] arg0) {
                Map<String, Object> item = Maps.newHashMap();
                for (int i = 0; i < arg0.length; i++) {
                    item.put(fileds[i], arg0[i]);
                }
                return item;
            }
        });
    }

    @Override
    @Transactional(readOnly = true)
    public BigInteger findCount(QueryTemplate qt) {
        Preconditions.checkArgument(!(qt instanceof SqlResultSetMappingQueryTemplate),
                "SqlResultMappingQueryTemplate can't use for count");
        List<Object[]> results = find(qt);
        if (results.size() > 0) {
            Object count = results.get(0)[0];
            // JPA
            if (count instanceof Long) {
                return BigInteger.valueOf((Long) count);
            }
            // SQL
            if (count instanceof BigInteger) {
                return (BigInteger) count;
            }
        }
        return BigInteger.ZERO;
    }

    @Override
    @Transactional(readOnly = true)
    public E find(ID id) {
        if (id == null)
            return null;
        return entityManager().find(persistentClass, id);
    }

    @Override
    @Transactional(readOnly = true)
    public List<E> findDomains(QueryTemplate qt) {
        Preconditions.checkArgument(!(qt instanceof SqlQueryTemplate),
                "SqlgQueryTemplate can't find Generic domain");
        Query query = createQuery(qt, persistentClass);

        @SuppressWarnings("unchecked")
        List<E> result = query.getResultList();
        return result;
    }

    @Override
    @Transactional(readOnly = true)
    public E findFirstDomain(QueryTemplate qt) {
        Preconditions.checkArgument(!(qt instanceof SqlQueryTemplate),
                "SqlgQueryTemplate can't find Generic domain");
        qt.setMaxResults(1);
        List<E> results = findDomains(qt);
        if (results.size() > 0) {
            return results.get(0);
        }
        // 
        return null;
    }

    @Override
    @Transactional(readOnly = true)
    public <S, P extends PageQuery<S>> Pagination<E> findDomainPage(QueryType qlType, PageQuery<S> queryPage,
            PaginationBuilder<S, P> builder) {
        Pagination<E> pagination = new Pagination<E>();
        // 
        pagination.setCount(findCountOfPages(qlType, queryPage, builder));
        QueryTemplate resultQt = buildResultOfPages(qlType, queryPage, builder);
        // 
        pagination.setResults(findDomains(resultQt));
        pagination.setCurrPage(queryPage.getCurrPage());
        // ?
        pagination.setPageSize(queryPage.getPageSize());
        return pagination;
    }

    /**
     * 
     *
     * @param qlType
     * @param queryPage
     * @param builder
     * @return
     */
    private <S, P extends PageQuery<S>> QueryTemplate buildResultOfPages(QueryType qlType, PageQuery<S> queryPage,
            PaginationBuilder<S, P> builder) {
        // ?
        QueryTemplate resultQt = QueryTemplate.create(qlType);
        // ?
        resultQt.setFirstResult(queryPage.getFirstResult());
        resultQt.setMaxResults(queryPage.getMaxResults());
        // ?
        builder.buildSelect(resultQt);
        resultQt.append(QueryConstants.WHERE);
        builder.buildWhere(queryPage.getSearchForm(), resultQt);
        builder.buildBys(queryPage.getSortColumn(), queryPage.getOrder(), resultQt);
        return resultQt;
    }

    /**
     * 
     *
     * @param qlType
     * @param queryPage
     * @param builder
     * @param pagination
     */
    private <S, P extends PageQuery<S>> int findCountOfPages(QueryType qlType, PageQuery<S> queryPage,
            PaginationBuilder<S, P> builder) {
        // ?
        QueryTemplate countQt = QueryTemplate.create(qlType);
        builder.buildCount(countQt);
        // ?
        if (countQt.isEmpty()) {
            return 0;
        }
        countQt.append(QueryConstants.WHERE);
        builder.buildWhere(queryPage.getSearchForm(), countQt);
        builder.buildBys(queryPage.getSortColumn(), queryPage.getOrder(), countQt);
        // 
        return findCount(countQt).intValue();
    }

    @Override
    @Transactional(readOnly = true)
    public <S, P extends PageQuery<S>> Pagination<Object[]> findArrayPage(QueryType qlType, PageQuery<S> queryPage,
            PaginationBuilder<S, P> builder) {
        Pagination<Object[]> pagination = new Pagination<Object[]>();
        // ?
        pagination.setCount(findCountOfPages(qlType, queryPage, builder));
        // 
        QueryTemplate resultQt = buildResultOfPages(qlType, queryPage, builder);
        pagination.setResults(find(resultQt));
        pagination.setCurrPage(queryPage.getCurrPage());
        return pagination;
    }

    @Override
    @Transactional(readOnly = true)
    public <S, P extends PageQuery<S>> Pagination<Map<String, Object>> findMapPage(QueryType qlType,
            PageQuery<S> queryPage, String[] fields, PaginationBuilder<S, P> builder) {
        Pagination<Map<String, Object>> pagination = new Pagination<Map<String, Object>>();
        // ?
        pagination.setCount(findCountOfPages(qlType, queryPage, builder));
        // 
        QueryTemplate resultQt = buildResultOfPages(qlType, queryPage, builder);
        pagination.setResults(find(resultQt, fields));
        pagination.setCurrPage(queryPage.getCurrPage());
        return pagination;
    }

    @Override
    @Transactional(readOnly = true)
    public E getReference(ID id) {
        return entityManager().getReference(persistentClass, id);
    }

    @Override
    @Transactional(readOnly = true)
    public Session getSession() {
        return entityManager().unwrap(Session.class);
    }

    @Override
    public boolean isExist(ID id) {
        return getReference(id) != null;
    }

    @Override
    public boolean isExist(Class<?> resultClass, Map<String, Object> parameters) {
        QueryTemplate qt = QueryTemplate.create(QueryType.JQL,
                "SELECT t FROM " + resultClass.getSimpleName() + " t");
        if (parameters.size() != 0)
            qt.append(" WHERE 1 = 1");
        for (Entry<String, Object> parameter : parameters.entrySet()) {
            qt.append(" AND t." + parameter.getKey() + " = :" + parameter.getKey());
            qt.addParameter(parameter.getKey(), parameter.getValue());
        }
        return findFirstDomain(qt) != null;
    }

    @Override
    @Transactional
    public E merge(E entity) {
        return entityManager().merge(entity);
    }

    @Override
    @Transactional
    public void persist(E entity) {
        if (!entity.hasId()) {
            entityManager().persist(entity);
        }
    }

    @Override
    @Transactional
    public void detach(E entity) {
        if (entityManager().contains(entity)) {
            entityManager().detach(entity);
        }
    }

    @Override
    @Transactional
    public void refresh(E entity) {
        if (entityManager().contains(entity)) {
            entityManager().refresh(entity);
        }
    }

    @Override
    @Transactional
    public void remove(E entity) {
        if (entityManager().contains(entity)) {
            entityManager().remove(entity);
        } else {
            remove(entity.getId());
        }
    }

    @Override
    @Transactional
    public void remove(ID id) {
        E entityRef = getReference(id);
        if (entityRef != null) {
            entityManager().remove(entityRef);
        }
    }

    @Override
    @Transactional
    public void removeBatch(ID[] ids) {
        if (ids != null) {
            for (ID id : ids) {
                remove(id);
            }
        }
    }

    @Override
    @Transactional
    public void removeBatch(Collection<E> entitys) {
        if (entitys != null) {
            for (E e : entitys) {
                remove(e);
            }
        }
    }

    @Override
    @Transactional
    public void clear() {
        entityManager().clear();
    }

    @Override
    @Transactional
    public void flush() {
        entityManager().flush();
    }

}