Java tutorial
/******************************************************************************* * Copyright 2012 Christian Ternes and Thorsten Volland * * 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.businessmanager.dao; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SingularAttribute; import org.businessmanager.dao.em.FilteredEntityManager; import org.businessmanager.domain.AbstractEntity; import org.businessmanager.domain.ModificationType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; /** * * Generic DAO-Implementation to support standard DAO methods (CRUD). * * @author Christian Ternes * @param <T> an entity class */ public abstract class GenericDaoImpl<T extends AbstractEntity> implements GenericDao<T> { @Autowired @Qualifier("filteredEntityManager") private EntityManager entityManager; @Autowired @Qualifier("TransactionManager") private PlatformTransactionManager txManager; public abstract Class<T> getPersistenceClass(); @Override public T save(T domainObject) { entityManager.persist(domainObject); return domainObject; } @Override public T update(T domainObject) { entityManager.merge(domainObject); return domainObject; } @Override public void remove(T domainObject) { entityManager.merge(domainObject); } @Override public void removePhysical(T domainObject) { T entity = entityManager.merge(domainObject); entityManager.remove(entity); } @Override public List<T> findAll(SingularAttribute<T, ?> orderAttribute, boolean orderAsc) { return findAll(orderAttribute, orderAsc, -1, -1); } @Override public List<T> findAll(SingularAttribute<T, ?> orderAttribute, boolean orderAsc, int firstResult, int maxResults) { return findAll(orderAttribute, orderAsc, firstResult, maxResults, null); } @Override public List<T> findAll(SingularAttribute<T, ?> orderAttribute, boolean orderAsc, int firstResult, int maxResults, Map<SingularAttribute<T, ?>, Object> filterAttributes) { return findAll(orderAttribute, orderAsc, firstResult, maxResults, filterAttributes, false); } @Override public List<T> findAll(SingularAttribute<T, ?> orderAttribute, boolean orderAsc, int firstResult, int maxResults, Map<SingularAttribute<T, ?>, Object> filterAttributes, boolean enableLikeSearch) { CriteriaBuilder queryBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<T> criteriaQuery = queryBuilder.createQuery(getPersistenceClass()); Root<T> rootQuery = criteriaQuery.from(getPersistenceClass()); CriteriaQuery<T> select = criteriaQuery.select(rootQuery); List<Predicate> predicateList = createFilterList(filterAttributes, enableLikeSearch, queryBuilder, rootQuery); select.where(predicateList.toArray(new Predicate[0])); if (orderAsc) { criteriaQuery.orderBy(queryBuilder.asc(rootQuery.get(orderAttribute))); } else { criteriaQuery.orderBy(queryBuilder.desc(rootQuery.get(orderAttribute))); } TypedQuery<T> typedQuery = entityManager.createQuery(criteriaQuery); if (firstResult != -1) { typedQuery.setFirstResult(firstResult); } if (maxResults != -1) { typedQuery.setMaxResults(maxResults); } return typedQuery.getResultList(); } @Override public T findById(Long id) { if (id == null) { return null; } //filter out deleted entities T entityFromDb = entityManager.find(getPersistenceClass(), id); if (entityFromDb instanceof AbstractEntity) { if (ModificationType.DELETE.equals(entityFromDb.getModificationType())) { return null; } } return entityFromDb; } @Override public List<T> findByAttribute(SingularAttribute<T, ?> key, Object value) { Map<SingularAttribute<T, ?>, Object> anAttributeMap = new HashMap<SingularAttribute<T, ?>, Object>(); anAttributeMap.put(key, value); return findByAttributes(anAttributeMap); } @Override public List<T> findByAttributes(Map<SingularAttribute<T, ?>, Object> theAttributes) { CriteriaBuilder queryBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<T> criteriaQuery = queryBuilder.createQuery(getPersistenceClass()); Root<T> rootQuery = criteriaQuery.from(getPersistenceClass()); CriteriaQuery<T> select = criteriaQuery.select(rootQuery); List<Predicate> aPredicateList = new ArrayList<Predicate>(); Iterator<SingularAttribute<T, ?>> anIterator = theAttributes.keySet().iterator(); while (anIterator.hasNext()) { SingularAttribute<T, ?> aKey = anIterator.next(); Object aValue = theAttributes.get(aKey); Predicate aPredicate = queryBuilder.equal(rootQuery.get(aKey), aValue); aPredicateList.add(aPredicate); } select.where(aPredicateList.toArray(new Predicate[0])); TypedQuery<T> typedQuery = entityManager.createQuery(select); return typedQuery.getResultList(); } @Override public Long getCount() { return getCount(null, false); } @Override public Long getCount(Map<SingularAttribute<T, ?>, Object> filterAttributes, boolean enableLikeSearch) { CriteriaBuilder queryBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> criteriaQuery = queryBuilder.createQuery(Long.class); Root<T> rootQuery = criteriaQuery.from(getPersistenceClass()); CriteriaQuery<Long> select = criteriaQuery.select(queryBuilder.count(rootQuery)); List<Predicate> predicateList = createFilterList(filterAttributes, enableLikeSearch, queryBuilder, rootQuery); criteriaQuery.where(predicateList.toArray(new Predicate[0])); TypedQuery<Long> typedQuery = entityManager.createQuery(select); return typedQuery.getSingleResult(); } @SuppressWarnings("unchecked") private List<Predicate> createFilterList(Map<SingularAttribute<T, ?>, Object> filterAttributes, boolean enableLikeSearch, CriteriaBuilder queryBuilder, Root<T> rootQuery) { List<Predicate> predicateList = new ArrayList<Predicate>(); if (filterAttributes != null) { Iterator<SingularAttribute<T, ?>> iter = filterAttributes.keySet().iterator(); while (iter.hasNext()) { SingularAttribute<T, ?> key = iter.next(); Object value = filterAttributes.get(key); if (enableLikeSearch) { String searchKey = value.toString(); if (!value.toString().contains("%")) { searchKey = "%" + value.toString() + "%"; } Expression<String> lowerKey = queryBuilder.lower((Expression<String>) rootQuery.get(key)); Predicate predicate = queryBuilder.like(lowerKey, searchKey.toLowerCase()); predicateList.add(predicate); } else { Predicate predicate = queryBuilder.equal(rootQuery.get(key), value); predicateList.add(predicate); } } } return predicateList; } @Override public TransactionStatus getTransaction() { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setName("CustomTransaction"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); return txManager.getTransaction(def); } @Override public void commit(TransactionStatus status) { txManager.commit(status); } @Override public void rollback(TransactionStatus status) { txManager.rollback(status); } protected EntityManager getEntityManager() { return entityManager; } protected FilteredEntityManager getFilteredEntityManager() { if (entityManager instanceof FilteredEntityManager) { return (FilteredEntityManager) entityManager; } else { throw new IllegalStateException("Current entity manager is not filtered."); } } /** * Allow subclasses to inject their own entity manager. * This is useful when multiple datasources/entity managers will be used. * * @param em the entity manager */ protected void setEntityManager(EntityManager em) { this.entityManager = em; } public List<T> findByAssignedEntity(ListAttribute<T, ?> listAttribute, Long entityId) { CriteriaBuilder queryBuilder = getEntityManager().getCriteriaBuilder(); CriteriaQuery<T> criteriaQuery = queryBuilder.createQuery(getPersistenceClass()); Root<T> rootQuery = criteriaQuery.from(getPersistenceClass()); CriteriaQuery<T> select = criteriaQuery.select(rootQuery); Join<T, ?> memberJoin = rootQuery.join(listAttribute); Path<?> nameField = memberJoin.get("id"); Predicate nameEquals = queryBuilder.equal(nameField, entityId); criteriaQuery.where(nameEquals); TypedQuery<T> typedQuery = getEntityManager().createQuery(select); return typedQuery.getResultList(); } public List<T> findByAssignedEntity(SetAttribute<T, ?> setAttribute, Long entityId) { CriteriaBuilder queryBuilder = getEntityManager().getCriteriaBuilder(); CriteriaQuery<T> criteriaQuery = queryBuilder.createQuery(getPersistenceClass()); Root<T> rootQuery = criteriaQuery.from(getPersistenceClass()); CriteriaQuery<T> select = criteriaQuery.select(rootQuery); Join<T, ?> memberJoin = rootQuery.join(setAttribute); Path<?> nameField = memberJoin.get("id"); Predicate nameEquals = queryBuilder.equal(nameField, entityId); criteriaQuery.where(nameEquals); TypedQuery<T> typedQuery = getEntityManager().createQuery(select); return typedQuery.getResultList(); } }