package com.jspxcms.common.orm; import static org.springframework.data.jpa.repository.query.QueryUtils.toOrders; import java.io.Serializable; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport; import org.springframework.data.jpa.repository.support.LockMetadataProvider; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.util.Assert; /** * Simple JPA Repository * * @author liufang * * @param <T> * @param <ID> */ public class MySimpleJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyJpaRepository<T, ID>, MyJpaSpecificationExecutor<T> { private final JpaEntityInformation<T, ?> entityInformation; private final EntityManager em; private LockMetadataProvider lockMetadataProvider; public MySimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.entityInformation = entityInformation; this.em = entityManager; } public MySimpleJpaRepository(Class<T> domainClass, EntityManager em) { this(JpaEntityInformationSupport.getMetadata(domainClass, em), em); } public void setLockMetadataProvider( LockMetadataProvider lockMetadataProvider) { super.setLockMetadataProvider(lockMetadataProvider); this.lockMetadataProvider = lockMetadataProvider; } private Class<T> getDomainClass() { return entityInformation.getJavaType(); } public List<T> findAll(Limitable limitable) { if (limitable != null) { TypedQuery<T> query = getQuery(null, limitable.getSort()); Integer firstResult = limitable.getFirstResult(); if (firstResult != null && firstResult > 0) { query.setFirstResult(firstResult); } Integer maxResults = limitable.getMaxResults(); if (maxResults != null && maxResults > 0) { query.setMaxResults(maxResults); } return query.getResultList(); } else { return findAll(); } } public List<T> findAll(Specification<T> spec, Limitable limitable) { if (limitable != null) { TypedQuery<T> query = getQuery(spec, limitable.getSort()); if (limitable.getFirstResult() != null) { query.setFirstResult(limitable.getFirstResult()); } if (limitable.getMaxResults() != null) { query.setMaxResults(limitable.getMaxResults()); } return query.getResultList(); } else { return findAll(spec); } } private TypedQuery<T> getQuery(Specification<T> spec, Sort sort) { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<T> query = builder.createQuery(getDomainClass()); Root<T> root = applySpecificationToCriteria(spec, query); query.select(root); if (sort != null) { query.orderBy(toOrders(sort, root, builder)); } return applyLockMode(em.createQuery(query)); } private <S> Root<T> applySpecificationToCriteria(Specification<T> spec, CriteriaQuery<S> query) { Assert.notNull(query); Root<T> root = query.from(getDomainClass()); if (spec == null) { return root; } CriteriaBuilder builder = em.getCriteriaBuilder(); Predicate predicate = spec.toPredicate(root, query, builder); if (predicate != null) { query.where(predicate); } return root; } private TypedQuery<T> applyLockMode(TypedQuery<T> query) { LockModeType type = lockMetadataProvider == null ? null : lockMetadataProvider.getLockModeType(); return type == null ? query : query.setLockMode(type); } }