简体   繁体   English

Spring JPA @事务性数据访问

[英]Spring JPA @Transactional data accessing

im having trouble resolving or handling data between my @Transational methods.我在我的@Transational方法之间解析或处理数据时遇到问题。 Or i may have a wrong understanding of @Transactionl .或者我可能对@Transactionl有错误的理解。

This is my scenario这是我的场景

Method A

@Transactional
public void methodA {
   MyEntity e = myRepo.findByid(1).orElseThrow();

   e.setMyFlag(1123);

   methodB();

   myRepo.save(e);
}


@Transactional 
public void methodB {
    MyEntity e = myRepo.findByMyFlag(1123).orElseThrow(); <--- This throws Not Found Exception
    // do something 'e' entity that is having a myFlag = 1123
    // i am not modifying the entity just doing something externally 
    // using myFlag value 1123
}

My understanding is that, methodB is using the session in methodA .我的理解是, methodB在 methodA 中使用methodA Now, given that it is using the same session, i can get the data set in methodA that was not yet commited or save() is not yet called.现在,鉴于它使用相同的methodA ,我可以获取尚未提交或尚未调用save()的方法 A 中的数据集。 Please do correct me if i am wrong and point me to the correct one.如果我错了,请纠正我并指出正确的。 Also, the above scenario is what i wanted to achieve.另外,上面的场景是我想要实现的。

FYI i also tried moving methodB call after save() call.仅供参考,我还尝试在save()调用之后移动methodB调用。 Still Not found exception occurs仍然Not found异常发生

You're right that it uses the same session and it is part of the same transaction.没错,它使用相同的 session 并且它是同一事务的一部分。 Where you're mistaken is that setting the value in the entity (without having saved yet) puts it anywhere that doing another query will find it.您错误的地方是在实体中设置值(尚未保存)将其放在任何进行另一个查询会找到它的地方。

In other words, the findByMyFlag in methodB is still not going to find the entity which you just modified, because the value you're searching on hasn't been saved to the database, yet.换句话说,methodB 中的 findByMyFlag 仍然不会找到您刚刚修改的实体,因为您正在搜索的值尚未保存到数据库中。

If, on the other hand, you had searched in methodB using findByid(1), then you would have found the same entity that would have that change in it.另一方面,如果您使用 findByid(1) 在方法 B 中进行了搜索,那么您将找到具有该更改的同一实体。

In the same class, a method calls another annotated method (such as @Async, @Transational), the annotation will not take effect在同一个class中,一个方法调用另一个注解的方法(如@Async、@Transational),注解不会生效

It is only from the various comments that you have added the answer can be deduced ie your question itself fails to give all relevant information.只有从您添加的各种评论中才能推断出答案,即您的问题本身未能提供所有相关信息。

You note that you look up query is "just a normal @Query(value="select * from my_table where my_flag =?1", nativeSql=true)".您注意到您查找的查询是“只是一个普通的@Query(value="select * from my_table where my_flag =?1", nativeSql=true)”。

And that is your problem: the fact you are executing a native sql query rather than a JPQL query.这就是您的问题:您正在执行本机sql 查询而不是 JPQL 查询。

If this was aa JPQL query then any pending changes in the same transaction would be flsuhed to the database (not committed, only flushed) in order that the query returned accurate results ie.e.如果这是一个 JPQL 查询,那么同一事务中的任何未决更改都将被刷新到数据库(不提交,仅刷新),以便查询返回准确的结果,即reflected any changes pending but not yet flushed to the database.反映了任何未决但尚未刷新到数据库的更改。

See further here for a more detailed explanation:请参阅此处以获取更详细的说明:

https://vladmihalcea.com/how-does-the-auto-flush-work-in-jpa-and-hibernate/ https://vladmihalcea.com/how-does-the-auto-flush-work-in-jpa-and-hibernate/

So to fix your problem change your query to:因此,要解决您的问题,请将您的查询更改为:

@Query(value="select e from MyEntity e where e.myFlag =?1") ie a JPQL query which will trigger a flush of pending changes. @Query(value="select e from MyEntity e where e.myFlag =?1")即一个 JPQL 查询,它将触发待处理更改的刷新。

Even moving myRepo.save(e);甚至移动myRepo.save(e); above the call to methodB() will not fix it.以上对 methodB() 的调用不会修复它。 You would need to save and flush for the native query to find it.您需要保存刷新本机查询才能找到它。

Which begs the question, why are you using a native query?这就引出了一个问题,为什么要使用本机查询?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM