【Spring Data Jpa學習】SimpleJpaRepository原始碼
阿新 • • 發佈:2018-11-25
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.data.jpa.repository.support; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Map.Entry; import java.util.function.Consumer; import java.util.function.LongSupplier; import java.util.function.Supplier; import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.convert.QueryByExamplePredicateBuilder; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.jpa.repository.query.QueryUtils; import org.springframework.data.jpa.repository.support.QueryHints.NoHints; import org.springframework.data.repository.support.PageableExecutionUtils; import org.springframework.lang.Nullable; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @Repository @Transactional( readOnly = true ) public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> { private static final String ID_MUST_NOT_BE_NULL = "The given id must not be null!"; private final JpaEntityInformation<T, ?> entityInformation; private final EntityManager em; private final PersistenceProvider provider; @Nullable private CrudMethodMetadata metadata; public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) { Assert.notNull(entityInformation, "JpaEntityInformation must not be null!"); Assert.notNull(entityManager, "EntityManager must not be null!"); this.entityInformation = entityInformation; this.em = entityManager; this.provider = PersistenceProvider.fromEntityManager(entityManager); } public SimpleJpaRepository(Class<T> domainClass, EntityManager em) { this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em); } public void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata) { this.metadata = crudMethodMetadata; } @Nullable protected CrudMethodMetadata getRepositoryMethodMetadata() { return this.metadata; } protected Class<T> getDomainClass() { return this.entityInformation.getJavaType(); } private String getDeleteAllQueryString() { return QueryUtils.getQueryString("delete from %s x", this.entityInformation.getEntityName()); } private String getCountQueryString() { String countQuery = String.format("select count(%s) from %s x", this.provider.getCountQueryPlaceholder(), "%s"); return QueryUtils.getQueryString(countQuery, this.entityInformation.getEntityName()); } @Transactional public void deleteById(ID id) { Assert.notNull(id, "The given id must not be null!"); this.delete(this.findById(id).orElseThrow(() -> { return new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", this.entityInformation.getJavaType(), id), 1); })); } @Transactional public void delete(T entity) { Assert.notNull(entity, "The entity must not be null!"); this.em.remove(this.em.contains(entity) ? entity : this.em.merge(entity)); } @Transactional public void deleteAll(Iterable<? extends T> entities) { Assert.notNull(entities, "The given Iterable of entities not be null!"); Iterator var2 = entities.iterator(); while(var2.hasNext()) { T entity = var2.next(); this.delete(entity); } } @Transactional public void deleteInBatch(Iterable<T> entities) { Assert.notNull(entities, "The given Iterable of entities not be null!"); if (entities.iterator().hasNext()) { QueryUtils.applyAndBind(QueryUtils.getQueryString("delete from %s x", this.entityInformation.getEntityName()), entities, this.em).executeUpdate(); } } @Transactional public void deleteAll() { Iterator var1 = this.findAll().iterator(); while(var1.hasNext()) { T element = var1.next(); this.delete(element); } } @Transactional public void deleteAllInBatch() { this.em.createQuery(this.getDeleteAllQueryString()).executeUpdate(); } public Optional<T> findById(ID id) { Assert.notNull(id, "The given id must not be null!"); Class<T> domainType = this.getDomainClass(); if (this.metadata == null) { return Optional.ofNullable(this.em.find(domainType, id)); } else { LockModeType type = this.metadata.getLockModeType(); Map<String, Object> hints = this.getQueryHints().withFetchGraphs(this.em).asMap(); return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints)); } } protected QueryHints getQueryHints() { return (QueryHints)(this.metadata == null ? NoHints.INSTANCE : DefaultQueryHints.of(this.entityInformation, this.metadata)); } public T getOne(ID id) { Assert.notNull(id, "The given id must not be null!"); return this.em.getReference(this.getDomainClass(), id); } public boolean existsById(ID id) { Assert.notNull(id, "The given id must not be null!"); if (this.entityInformation.getIdAttribute() == null) { return this.findById(id).isPresent(); } else { String placeholder = this.provider.getCountQueryPlaceholder(); String entityName = this.entityInformation.getEntityName(); Iterable<String> idAttributeNames = this.entityInformation.getIdAttributeNames(); String existsQuery = QueryUtils.getExistsQueryString(entityName, placeholder, idAttributeNames); TypedQuery<Long> query = this.em.createQuery(existsQuery, Long.class); if (!this.entityInformation.hasCompositeId()) { query.setParameter((String)idAttributeNames.iterator().next(), id); return (Long)query.getSingleResult() == 1L; } else { Iterator var7 = idAttributeNames.iterator(); while(var7.hasNext()) { String idAttributeName = (String)var7.next(); Object idAttributeValue = this.entityInformation.getCompositeIdAttributeValue(id, idAttributeName); boolean complexIdParameterValueDiscovered = idAttributeValue != null && !query.getParameter(idAttributeName).getParameterType().isAssignableFrom(idAttributeValue.getClass()); if (complexIdParameterValueDiscovered) { return this.findById(id).isPresent(); } query.setParameter(idAttributeName, idAttributeValue); } return (Long)query.getSingleResult() == 1L; } } } public List<T> findAll() { return this.getQuery((Specification)null, (Sort)Sort.unsorted()).getResultList(); } public List<T> findAllById(Iterable<ID> ids) { Assert.notNull(ids, "The given Iterable of Id's must not be null!"); if (!ids.iterator().hasNext()) { return Collections.emptyList(); } else if (!this.entityInformation.hasCompositeId()) { SimpleJpaRepository.ByIdsSpecification<T> specification = new SimpleJpaRepository.ByIdsSpecification(this.entityInformation); TypedQuery<T> query = this.getQuery(specification, (Sort)Sort.unsorted()); return query.setParameter(specification.parameter, ids).getResultList(); } else { List<T> results = new ArrayList(); Iterator var3 = ids.iterator(); while(var3.hasNext()) { ID id = var3.next(); this.findById(id).ifPresent(results::add); } return results; } } public List<T> findAll(Sort sort) { return this.getQuery((Specification)null, (Sort)sort).getResultList(); } public Page<T> findAll(Pageable pageable) { return (Page)(isUnpaged(pageable) ? new PageImpl(this.findAll()) : this.findAll((Specification)null, pageable)); } public Optional<T> findOne(@Nullable Specification<T> spec) { try { return Optional.of(this.getQuery(spec, Sort.unsorted()).getSingleResult()); } catch (NoResultException var3) { return Optional.empty(); } } public List<T> findAll(@Nullable Specification<T> spec) { return this.getQuery(spec, Sort.unsorted()).getResultList(); } public Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable) { TypedQuery<T> query = this.getQuery(spec, pageable); return (Page)(isUnpaged(pageable) ? new PageImpl(query.getResultList()) : this.readPage(query, this.getDomainClass(), pageable, spec)); } public List<T> findAll(@Nullable Specification<T> spec, Sort sort) { return this.getQuery(spec, sort).getResultList(); } public <S extends T> Optional<S> findOne(Example<S> example) { try { return Optional.of(this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType(), (Sort)Sort.unsorted()).getSingleResult()); } catch (NoResultException var3) { return Optional.empty(); } } public <S extends T> long count(Example<S> example) { return executeCountQuery(this.getCountQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType())); } public <S extends T> boolean exists(Example<S> example) { return !this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType(), (Sort)Sort.unsorted()).getResultList().isEmpty(); } public <S extends T> List<S> findAll(Example<S> example) { return this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType(), (Sort)Sort.unsorted()).getResultList(); } public <S extends T> List<S> findAll(Example<S> example, Sort sort) { return this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType(), (Sort)sort).getResultList(); } public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) { SimpleJpaRepository.ExampleSpecification<S> spec = new SimpleJpaRepository.ExampleSpecification(example); Class<S> probeType = example.getProbeType(); TypedQuery<S> query = this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), probeType, (Pageable)pageable); return (Page)(isUnpaged(pageable) ? new PageImpl(query.getResultList()) : this.readPage(query, probeType, pageable, spec)); } public long count() { return (Long)this.em.createQuery(this.getCountQueryString(), Long.class).getSingleResult(); } public long count(@Nullable Specification<T> spec) { return executeCountQuery(this.getCountQuery(spec, this.getDomainClass())); } @Transactional public <S extends T> S save(S entity) { if (this.entityInformation.isNew(entity)) { this.em.persist(entity); return entity; } else { return this.em.merge(entity); } } @Transactional public <S extends T> S saveAndFlush(S entity) { S result = this.save(entity); this.flush(); return result; } @Transactional public <S extends T> List<S> saveAll(Iterable<S> entities) { Assert.notNull(entities, "The given Iterable of entities not be null!"); List<S> result = new ArrayList(); Iterator var3 = entities.iterator(); while(var3.hasNext()) { S entity = var3.next(); result.add(this.save(entity)); } return result; } @Transactional public void flush() { this.em.flush(); } /** @deprecated */ @Deprecated protected Page<T> readPage(TypedQuery<T> query, Pageable pageable, @Nullable Specification<T> spec) { return this.readPage(query, this.getDomainClass(), pageable, spec); } protected <S extends T> Page<S> readPage(TypedQuery<S> query, Class<S> domainClass, Pageable pageable, @Nullable Specification<S> spec) { if (pageable.isPaged()) { query.setFirstResult((int)pageable.getOffset()); query.setMaxResults(pageable.getPageSize()); } return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> { return executeCountQuery(this.getCountQuery(spec, domainClass)); }); } protected TypedQuery<T> getQuery(@Nullable Specification<T> spec, Pageable pageable) { Sort sort = pageable.isPaged() ? pageable.getSort() : Sort.unsorted(); return this.getQuery(spec, this.getDomainClass(), sort); } protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Pageable pageable) { Sort sort = pageable.isPaged() ? pageable.getSort() : Sort.unsorted(); return this.getQuery(spec, domainClass, sort); } protected TypedQuery<T> getQuery(@Nullable Specification<T> spec, Sort sort) { return this.getQuery(spec, this.getDomainClass(), sort); } protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Sort sort) { CriteriaBuilder builder = this.em.getCriteriaBuilder(); CriteriaQuery<S> query = builder.createQuery(domainClass); Root<S> root = this.applySpecificationToCriteria(spec, domainClass, query); query.select(root); if (sort.isSorted()) { query.orderBy(QueryUtils.toOrders(sort, root, builder)); } return this.applyRepositoryMethodMetadata(this.em.createQuery(query)); } /** @deprecated */ @Deprecated protected TypedQuery<Long> getCountQuery(@Nullable Specification<T> spec) { return this.getCountQuery(spec, this.getDomainClass()); } protected <S extends T> TypedQuery<Long> getCountQuery(@Nullable Specification<S> spec, Class<S> domainClass) { CriteriaBuilder builder = this.em.getCriteriaBuilder(); CriteriaQuery<Long> query = builder.createQuery(Long.class); Root<S> root = this.applySpecificationToCriteria(spec, domainClass, query); if (query.isDistinct()) { query.select(builder.countDistinct(root)); } else { query.select(builder.count(root)); } query.orderBy(Collections.emptyList()); return this.em.createQuery(query); } private <S, U extends T> Root<U> applySpecificationToCriteria(@Nullable Specification<U> spec, Class<U> domainClass, CriteriaQuery<S> query) { Assert.notNull(domainClass, "Domain class must not be null!"); Assert.notNull(query, "CriteriaQuery must not be null!"); Root<U> root = query.from(domainClass); if (spec == null) { return root; } else { CriteriaBuilder builder = this.em.getCriteriaBuilder(); Predicate predicate = spec.toPredicate(root, query, builder); if (predicate != null) { query.where(predicate); } return root; } } private <S> TypedQuery<S> applyRepositoryMethodMetadata(TypedQuery<S> query) { if (this.metadata == null) { return query; } else { LockModeType type = this.metadata.getLockModeType(); TypedQuery<S> toReturn = type == null ? query : query.setLockMode(type); this.applyQueryHints(toReturn); return toReturn; } } private void applyQueryHints(Query query) { Iterator var2 = this.getQueryHints().withFetchGraphs(this.em).iterator(); while(var2.hasNext()) { Entry<String, Object> hint = (Entry)var2.next(); query.setHint((String)hint.getKey(), hint.getValue()); } } private static long executeCountQuery(TypedQuery<Long> query) { Assert.notNull(query, "TypedQuery must not be null!"); List<Long> totals = query.getResultList(); long total = 0L; Long element; for(Iterator var4 = totals.iterator(); var4.hasNext(); total += element == null ? 0L : element) { element = (Long)var4.next(); } return total; } private static boolean isUnpaged(Pageable pageable) { return pageable.isUnpaged(); } private static class ExampleSpecification<T> implements Specification<T> { private static final long serialVersionUID = 1L; private final Example<T> example; ExampleSpecification(Example<T> example) { Assert.notNull(example, "Example must not be null!"); this.example = example; } public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) { return QueryByExamplePredicateBuilder.getPredicate(root, cb, this.example); } } private static final class ByIdsSpecification<T> implements Specification<T> { private static final long serialVersionUID = 1L; private final JpaEntityInformation<T, ?> entityInformation; @Nullable ParameterExpression<Iterable> parameter; ByIdsSpecification(JpaEntityInformation<T, ?> entityInformation) { this.entityInformation = entityInformation; } public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Path<?> path = root.get(this.entityInformation.getIdAttribute()); this.parameter = cb.parameter(Iterable.class); return path.in(new Expression[]{this.parameter}); } } }