首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >针对不同参数返回相同结果的JPA查询

针对不同参数返回相同结果的JPA查询
EN

Stack Overflow用户
提问于 2015-09-12 00:23:23
回答 3查看 8.1K关注 0票数 4

我遇到了一个问题,我的query方法在foreach循环中,每次我都会传入一个不同的参数来检索不同的信息。然而,在循环的第一次迭代之后,查询数据被缓存(我认为),并为后续循环返回相同的数据。

下面是我的代码:

代码语言:javascript
复制
@Transactional(readOnly = true)
public List<InitiativeReport> getInitiativeReports() throws Exception {
try {
    List<InitiativeReport> ir = new ArrayList<InitiativeReport>();
    List<Initiative> in = initiativeRepository.findAll();
    for(Initiative i : in) {
        i.getTheme().getId(); // lazy initialize

        InitiativeReport report = new InitiativeReport();
        report.setId(i.getId());
        report.setInitiativeId(i.getInitiativeId());
        report.setName(i.getName());
        report.setTheme(i.getTheme());

        // this is the call to the query, which is cached after the first iteration
        List<InitiativeProfileQuestion> q = initiativeProfileQuestionRepository.getQuestionsAndAnswerLogs(i.getInitiativeId());
        report.setQuestions(q);
        ir.add(report);
    }

    return ir;
}
catch (Exception e) {
    throw new Exception(e);
}

下面是我的存储库接口:

代码语言:javascript
复制
public interface InitiativeProfileQuestionRepository extends JpaRepository<InitiativeProfileQuestion, Long> {
    @Query("select distinct q from InitiativeProfileQuestion q "
         + "left join fetch q.answers "
         + "left join fetch q.answerLogs al "
         + "where al.initiative.initiativeId = ?1 "
         + "and al.revision = al.initiative.revision 
         + "order by q.question asc")
    public List<InitiativeProfileQuestion> getQuestionsAndAnswerLogs(String initiativeId);
}

这是我的application.yml文件:

代码语言:javascript
复制
spring:
    datasource:
        dataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlDataSource
        url: jdbc:mysql://localhost/testdb
        username: root
        password: XXXXXXXXX
        driverClassName: com.mysql.jdbc.Driver
        testOnBorrow: true
        validationQuery: SELECT 1
    jpa:
        database-platform: org.hibernate.dialect.MySQLInnoDBDialect
        database: MYSQL
        openInView: false
        show_sql: true
        generate-ddl: false
        hibernate:
            ddl-auto: none
            naming-strategy: org.hibernate.cfg.EJB3NamingStrategy

这个问题与我在这里找到的一个帖子非常相似:Native Query (JPA ) not reset and return the same old result

但是,用户正在使用EntityManager,而我的应用程序中没有EntityManager的实现--我让JPA完成所有工作,只有查询注释。

如有任何帮助,我们将不胜感激!

EN

回答 3

Stack Overflow用户

发布于 2018-03-23 22:32:51

有点晚了,但对于那些现在发现这一点的人来说,这是你需要做的来解决这个问题的方法:

当您在已经启动了一个事务的循环中进行查询时,您需要从该循环中共享相同id但可能具有不同数据的查询中分离返回的实体。

下面是一个例子:

代码语言:javascript
复制
@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ProductWarehouseRepository productWarehouseRepository;

    @Autowired
    private EntityManager entityManager;

    @Transactional
    public List<Product> getProducts(){
        List<Product> products = this.productRepository.findAll();
        products.forEach(product -> {
            List<ProductWarehouse> warehouses = this.productWarehouseRepository.findAllByProductId(product.getId());
            warehouses.forEach(warehouse -> {
                //THIS IS THE IMPORTANT PART
                //You have to detach the entity from the session
                this.entityManager.detach(warehouse);
            });
            product.setWarehouses(warehouses);
        });
        return products;
    }
}

在本例中,产品A可以在id为1的仓库中,产品B也可以在仓库中,但它们在仓库中的可用数量可能不同。

当返回的结果在@Id列上可能有冲突时,您必须从会话中分离实体。这与Hibernate中一级缓存的工作方式有关。您可以查看此链接以获取更多信息http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html

票数 11
EN

Stack Overflow用户

发布于 2016-04-07 08:20:56

我遇到了一个非常类似的问题。我通过更改实体类来解决这个问题,添加了一个额外的@Id注释,以准确地反映数据库表上的复合主键。你可能想试一试。

或者,看看我最近对上面提到的问题的回答(Native Query (JPA ) not reset and return the same old result)。正如您所注意到的,它与这个问题有一些相似之处。

此外,您的InitiativeProfileQuestion在变量id上显示@Id。看起来您是通过initiativeId查询的。也许您应该按id查询,因为它被注释为主键。

注意:我不明白为什么有人一开始就因为没有回答问题而删除了这篇文章。我试着把它作为评论发布,但我没有足够的名誉点来这么做。尽管如此,我相信我的建议可能会解决提问者的问题,所以我认为这是一个答案。我承认,它更多地可以被解释为建议而不是答案。但事实上,严格来说,我也不认为这是一个评论。提问者不应该是权衡这是否是答案的人吗?我的答案真的符合这些标准吗?:。

票数 4
EN

Stack Overflow用户

发布于 2018-08-29 08:10:21

我也有同样的问题,我搜索了很多网页,都找不到确切的解决方案。然后我发现下面的方法可以解决这个问题。

在查询前调用entityManager.clear()可以解决这个问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32527978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档