"查询"在生产中创建错误的SQL

时间:2016-02-01 17:27:39

标签: hibernate grails gorm grails-2.3

我必须将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和1 = 1)" 。实际上,这样的查询:

User.findAll {id == userid} 

检索整个表格。 动态查找程序或条件不会导致此问题。

我找到了两个有类似问题的人:

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

我使用的插件:

  • 弹簧安全核:2.0-RC5
  • 弹簧安全的OAuth:2.0.2
  • 弹簧安全OAuth的Facebook的:0.1
  • 休眠:3.6.10.16
  • 执行:0.3
  • 出口:1.6
  • CSV:0.3.1
  • 数据库迁移:1.2.1
  • 石英:1.0-RC7
  • 资产管道:1.9.6
  • 的grails-旋律:1.57.0

数据库:PostgreSQL 8.4.20

我尝试了很多解决方案:

  • 我将Grails版本更改为2.4
  • 我将Hibernate3更改为Hibernate4
  • 我将连接器更改为Postgres,从9.0-801.jdbc3更改为9.1-901-1.jdbc4
  • 我删除了依赖项以查看其中是否存在任何问题
  • 我检查了提取的WAR在任何文件中是否没有差异
  • 我更改了Java版本
  • 我更改了Tomcat版本
  • 我在另一个系统上测试

从我在上面给出的链接的博客上看到的,Graeme Rocher写道,问题可能是由于应用程序中缺少GORM。但是,在构建WAR期间存在问题 - 依赖项被错误地打包(?)。但是,当WAR解包或加载类时,会出现问题。从博客条目看问题的根源,表明问题可能是由于一些荒谬的原因......

有没有人知道可能导致此问题的原因或我可以调试哪些能够确定错误的来源? 以及grails开发的问题:版本2.2和2.3之间的变化在理论上可能会导致这样的问题吗?

2 个答案:

答案 0 :(得分:4)

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

此地图是criterionAdaptors,用于将GORM Criterions映射到Hibernate。

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

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

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

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

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

答案 1 :(得分:0)

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

你试过这个吗?

User.findAllById(userid)