use*_*214 3 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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的存储库界面:
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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的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
Run Code Online (Sandbox Code Playgroud)
这个问题与我在这里找到的帖子非常相似:本机查询(JPA)未重置并返回相同的旧结果
但是,该用户正在使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,产品A可以在仓库ID 1中,产品B可以在仓库ID中,但是它们在仓库中的可用数量可能不同。
当返回的结果可能在@Id列上发生冲突时,必须从会话中分离实体。这与Hibernate中1级缓存的工作方式有关。您可以查看此链接以获取更多信息http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html
我遇到了一个非常相似的问题。我通过更改实体类以添加额外的 @Id 注释来准确反映数据库表上的复合主键来解决此问题。您可能想尝试一下。
或者,看看我最近对上面提到的问题的回答(本机查询(JPA)不会重置并返回相同的旧结果)。正如您所注意到的,它与这个问题有一些相似之处。
此外,您的 InitiativeProfileQuestion 在变量 id 上显示@Id。看起来您正在通过 InitiativeId 进行查询。也许您应该通过 id 进行查询,因为它被注释为主键。
注意:我不明白为什么有人最初删除此内容是因为没有回答问题。我尝试将其作为评论发布,但我没有足够的声誉点来这样做。尽管如此,我确实相信我的建议可以解决提问者的问题,所以我认为这是一个答案。我同意它更多地可以被解释为建议而不是答案。但事实上,我也不会将其称为严格的评论。提问者不应该是权衡它是否是答案的人吗?我的答案是否真的符合这些标准?:https://stackoverflow.com/help/deleted-answers。
| 归档时间: |
|
| 查看次数: |
4046 次 |
| 最近记录: |