"Where query" 在生产中创建错误 SQL

"Where query" creates wrong SQL on production

我必须将 Spring 从 1.2.7 更新到 2.0,并将 Grails 从 2.2.0 更新到 2.3.11。在解决了几个典型的更新问题后,我开始搭建一个WAR到测试服务器。一切似乎都很好。但是部署了几次之后就遇到了问题

有时(没有规则)服务器有 100% CPU 使用率 -> OutOfMemeryError 或应用程序抛出错误 500。调试后,我发现这些问题的原因不正确 SQL查询。

哪里查询:

UserRole.find{role.authority =~ "%${authTxt}" && user.id == currentUser.id}

创建这样的 SQL:

select this_.id as id1_35_2_, this_.payment_enabled as payment_2_35_2_, this_.role_id as role_id3_35_2_, this_.user_id as user_id4_35_2_,
role_alias1_.id as id1_29_0_, role_alias1_.version as version2_29_0_, role_alias1_.authority as authorit3_29_0_, user_alias2_.id as id1_36_1_,
user_alias2_.version as version2_36_1_, user_alias2_.account_expired as account_3_36_1_, user_alias2_.account_locked as account_4_36_1_, 
user_alias2_.auto_password_flag as auto_pas5_36_1_, user_alias2_.email as email6_36_1_, user_alias2_.enabled as enabled7_36_1_, 
user_alias2_."password" as password8_36_1_, user_alias2_.password_expired as password9_36_1_, user_alias2_.user_info_id
as user_in10_36_1_, user_alias2_.username as usernam11_36_1_ from user_role this_ inner join role role_alias1_ on this_.role_id=role_alias1_.id inner join users user_alias2_ 
on this_.user_id=user_alias2_.id where (1=1 and 1=1)

这里是正确的 SQL:

... inner join role role_alias1_ on this_.role_id=role_alias1_.id inner join users user_alias2_ on this_.user_id=user_alias2_.id 
where ((role_alias1_.authority ilike ?) and (user_alias2_.id=?)) 

明显的问题是表达式 "(1 = 1 and 1 = 1)"。其实这样查询:

User.findAll {id == userid} 

检索整个 table。 动态查找器或标准不会导致此问题。

我发现有两个人有类似的问题:

https://zenofchicken.wordpress.com/2016/01/06/freaky-grails-where-clauses-dont-work-anymore/

http://grails.1312388.n4.nabble.com/Finder-not-applying-criteria-td4655689.html

我使用的插件:

数据库:PostgreSQL 8.4.20

我试过很多解决方案:

根据我在 link 我上面给出的博客上读到的内容,Graeme Rocher 写道,问题可能是由于应用程序中缺少 GORM。然而,问题是在 WAR 的构建过程中出现的——依赖项被错误地打包(?)。但是当 WAR 解包或 类 加载时,问题就出现了。从blog entry看问题的根源,表明问题可能是由于一些荒谬的原因...

有谁知道是什么导致了这个问题,或者我可以调试什么来确定错误的来源? 以及 grails dev 的问题:2.2 版和 2.3 版之间发生了什么理论上可能导致此类问题的变化?

问题似乎来自 grails-datastore-gorm-hibernate-core JAR 中的 AbstractHibernateCriterionAdapter
criterionAdaptors HashMap 未正确填充。

这个映射 final static HashMap 用于将 GORM 标准映射到 Hibernate 标准。

应用程序启动时随机出现此问题。
有时填充 HashMap 没有任何问题,有时会出现问题...
这个 Hashmap 是 static final 并且在应用程序生命周期的剩余时间内保持损坏。这就是为什么你有时会遇到这个问题,重启后一切正常。

当多个线程同时创建一个 AbstractHibernateCriterionAdapter 对象时,HashMap 可能会损坏。
每个线程调用构造函数和 initialize() 方法。
此方法是 synchronizedsynchronized 习惯用法仅对访问 同一对象的多个线程有效 (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)

因此,synchronized 没有正确锁定 initialize() 方法,多个线程可以尝试同时填充 criterionAdaptors HashMap。
HashMap 不是线程安全的,因此 HashMap 已损坏并且缺少一些条件。

如果在此 HashMap 中未找到 GORM 标准,则会默默地忽略该标准...这解释了为什么它会从生成的请求中消失。

我创建了一个 Github 问题:https://github.com/grails/grails-data-mapping/issues/643

通过 id 以这种方式获取所有 User 实例的方式很奇怪。

你试过吗?

User.findAllById(userid)