java - JPA 查询为不同的参数返回相同的结果

标签 java spring hibernate jpa spring-data

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

这是我的代码:

@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);
}

这是我的存储库界面:

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 文件:

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 完成所有工作并且只有查询注释。

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

最佳答案

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

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

举个例子:

@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 列发生冲突时,您必须从 session 中分离实体。这与 1 级缓存在 Hibernate 中的工作方式有关。您可以查看此链接以获取更多信息 http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html

关于java - JPA 查询为不同的参数返回相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32527978/

相关文章:

java - 如何将枚举类型存储为小写字符串?

hibernate - Grails 命名 id 列错误

java - 如何将连接驱动程序添加到我的项目中

部署 Tomcat 后 Java/Spring 应用卡住

java - 将外部化值注入(inject) Spring 注解

java - @PathVariable fileName 结果为 406 Not Acceptable

java - 将我的实体绑定(bind)到带有 @OneToMany 注释的表时,JPA/Hibernate 出现异常

java - 如何动态更改来自不同类的 View 背景颜色

java - 当似乎没有必要时将上下文存储在适配器中

java - 如何使用 firebase 身份验证创建用户名、地址和详细信息