一、问题
一大早来公司看到日志中显示:nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet
赶紧去排查问题,。
竟发现是一条sql存在的问题
-
来看下代码咯
二、分析
- 从上面报错信息所看到是sql语句执行时候问题
-
于是乎想到了两个注解 @Modifying 和 @Transactional
先看下官方文档针对这个注解的解释
As the queries themselves are tied to the Java method that executes them, you can actually bind them directly by using the Spring Data JPA @Query annotation
rather than annotating them to the domain class.
You can modify queries that only need parameter binding by annotating the query method with @ModifyingThe @Modifying annotation is only relevant in combination with the @Query annotation. Derived query methods or custom methods do not require this Annotation.Doing so triggers the query annotated to the method as an updating query instead of a selecting one.
由于查询本身与执行它们的Java方法相关联,因此实际上您可以使用Spring Data JPA @Query批注直接绑定它们
而不是将它们注释到域类。
您可以通过使用@Modifying注释查询方法来修改仅需要参数绑定的查询。@Modifying注释仅与@Query注释结合使用。派生的查询方法或自定义方法不需要此注释,这样做会触发对该方法注释的查询作为更新查询而不是选择查询。
-
@Query来注入我们自定义的sql;
-
使用@Modifying来标注是一个更新类的自定义语句。
下面我进就加上这个注解再去尝试
此时我们发现异常转换为了java事务
再加上@Transactional去试一下
官方说明啊:
By default, CRUD methods on repository instances are transactional. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain @Transactional so that default transaction configuration applies. For details, see JavaDoc of SimpleJpaRepository. If you need to tweak transaction configuration for one of the methods declared in a repository, redeclare the method in your repository interface, as follows:
Example. Custom transaction configuration for CRUD
默认情况下,存储库实例上的CRUD方法是事务性的。对于读取操作,事务配置readOnly标志设置为true。所有其他文件都配置有简单的@Transactional,以便应用默认事务配置。有关详细信息,请参见SimpleJpaRepository的JavaDoc。如果需要调整存储库中声明的方法之一的事务配置,请在存储库接口中重新声明该方法,如下所示:
例。 CRUD的自定义事务配置
默认情况下,repository 接口中的CRUD方法都是被@Transactional注解修饰了的,对于读的操作方法,@Transactional注解的readOnly属性是被设置为true的,即只读;CRUD中的其他方法被@Transactional修饰,即非只读。如果你需要修改repository 接口中的某些方法的事务属性,可以在该方法上重新加上@Transactional注解,并设置需要的属性。
看原发你会发现:
1)该类上注解了只读事务@Transactional(readOnly = true);
2)该类的所有查询类操作方法都与类相同,都拥有只读事务;
3)该类的所有保存、更新、删除操作方法都用@Transactional重新注解了(默认readOnly=false)。
至此,该方法按所期望的结果运行成功了。
三、总结
该注解中有两个属性:flushAutomatically、clearAutomatically,从字面理解是自动刷新和自动清除。
自动刷新,即执行完语句后立即将变化内容刷新到磁盘,
如果是insert语句操作,则与JPA的<S extends T> S saveAndFlush(S entity);方法效果相同;
自动清除,即执行完语句后自动清除掉已经过期的实体,
比如,我们删除了一个实体,但是在还没有执行flush操作时,
这个实体还存在于实体管理器EntityManager中,但这个实体已经过期没有任何用处,直到flush操作时才会被删除掉。
如果希望在删除该实体时立即将该实体从实体管理器中删除,则可以将该属性设置为true,
😁 作者:Teddy (公众号:鸡仓故事汇)
ok!到这里就大功告成,小编(Teddy)在这里先感谢大家的到来。
虽然不是太详细,小编已经很努力,给小编来个一键三连(点赞,关注,收藏),小编会越来越努力。。。