当前位置: 首页 > 知识库问答 >
问题:

Spring Data JPA+JpaSpecificationExecutor+EntityGraph

施鸿
2023-03-14

(使用Spring Data JPA)我有两个实体,它们之间具有一个或多个或多个双向关系。我将@NamedEntityGraph添加到父实体,如下所示:

@Entity
@NamedEntityGraph(name = "Parent.Offspring", attributeNodes = @NamedAttributeNodes("children"))
public class Parent{
//blah blah blah

@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
Set<Child> children;

//blah blah blah
}

请注意,父级子级的fetch类型是lazy的。这是故意的。当我询问个别家长时,我不想总是急切地加载孩子。通常情况下,我可以使用我的命名实体图来按需加载孩子们。但是.....

有一个特定的情况,我想查询一个或多个家长和迫切加载他们的孩子。除此之外,我还需要能够以编程方式构建这个查询。spring数据提供了JpaSpecificationExecutor,它允许构建动态查询,但我不知道如何将它与实体图结合使用,以便在这种特定情况下快速加载子项。这有可能吗?是否有其他方法可以使用规范将“加载到”许多实体中?

共有1个答案

鲁宏爽
2023-03-14

null

@NoRepositoryBean
public interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

    List<T> findAll(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);
    Page<T> findAll(Specification<T> spec, Pageable pageable, EntityGraphType entityGraphType, String entityGraphName);
    List<T> findAll(Specification<T> spec, Sort sort, EntityGraphType entityGraphType, String entityGraphName);
    T findOne(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);

}

还要创建一个实现:

@NoRepositoryBean
public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {

    private EntityManager em;

    public CustomRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.em = em;
    }

    @Override
    public List<T> findAll(Specification<T> spec, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
        TypedQuery<T> query = getQuery(spec, (Sort) null);
        query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
        return query.getResultList();
    }

    @Override
    public Page<T> findAll(Specification<T> spec, Pageable pageable, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
        TypedQuery<T> query = getQuery(spec, pageable.getSort());
        query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
        return readPage(query, pageable, spec);
    }

    @Override
    public List<T> findAll(Specification<T> spec, Sort sort, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
        TypedQuery<T> query = getQuery(spec, sort);
        query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
        return query.getResultList();
    }

    @Override
    public T findOne(Specification<T> spec, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
        TypedQuery<T> query = getQuery(spec, (Sort) null);
        query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
        return query.getSingleResult();
    }
}

并创建工厂:

public class CustomRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new CustomRepositoryFactory(entityManager);
    }

    private static class CustomRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

        public CustomRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new CustomRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            // The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
            //to check for QueryDslJpaRepository's which is out of scope.
            return CustomRepository.class;
        }
    }

}

并将默认的存储库工厂bean更改为新的bean,例如在spring boot,将此添加到配置中:

@EnableJpaRepositories(
    basePackages = {"your.package"},
    repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class
)

有关自定义存储库的更多信息:http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-behavior-for-all-repositories

 类似资料:
  • 我只想不使用xml,所以我需要非xml替代这些设置。这是我的POM。

  • 问题内容: 我使用spring数据和方法来获取模型。调用此方法时如何使用查询提示? 上面的源代码工作正常,但是我不能为我的JPA提供程序(在我的情况下为EclipseLink)设置QueryHint。 以上是我使用spring-data使用查询提示的方式, 我还发现了这个尚未解决的问题。 问题答案: 当我想使用spring-data创建查询时,请遵循上述算法。 1)是否已经提供的查询 通过弹簧数据

  • 我有两个实体。父母和孩子。 儿童知识库。JAVA 我试图通过标准找到子实体,它应该总是有父实体。 我得到一个例外,它试图在地址表中找到parentObj。 我找到了这个链接,并尝试了Joep给出的解决方案,但出现了相同的错误。 Spring数据JPA JpaSpecificationExecator EntityGgraph 我错过了什么。我无法理解为什么/如何在just Child对象中查找pa

  • 问题内容: 我有一个使用JOIN和ORDER BY的查询,并想使用Criteria Api在我的存储库中使用它。 在这里,我发现了如何将这样的查询包装到CriteriaQuery(Link)中。 另一方面,我发现了一些将Criteria Api与JpaRepository结合使用的示例(example)。 问题在于存储库中的所有方法都需要规范: 总是这样构建的: 因此,一方面,我知道如何创建Cri

  • 我正在尝试创建一个简单的Spring项目,餐厅可以在共享数据库中添加菜单项,用户可以使用html表单根据一系列标准搜索菜肴,尤其是饮食要求 表格示例: 示例SQL命令 然后,符合他们标准的菜肴列表将返回给用户。 表单中的任何字段都可以留空,不勾选框(例如,“素食主义者”并不意味着条件应设置为“假”,而是不包括在查询中)。因此,处理该问题的最佳方法似乎是使用JpaSpecificationExecu

  • 我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。 当我调用时,它会触发三个select查询: (“sql”) (对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当类中的更改为时,查询没有区别(使用附加选择进行查询),当更改为时,城市类的查询也一样(使用JOIN进行查询)。 当我使用抑制火灾时,有两种选择: 我的目标是在所有情况下