Grails - not-null属性仅对并发用户引用null或transient值错误

时间:2014-10-26 03:10:27

标签: hibernate grails gorm

我们在Grails中开发的Web应用程序最近已进入压力测试阶段,现在我们遇到了这个问题,似乎只有在多个用户(不同的用户帐户)同时执行相同的操作时才会发生这个问题时间。这些操作是事务性的,但它们都不在同一对象上执行(正在创建新对象)。我们得到的例外是:

  

类:org.hibernate.PropertyValueException   消息:not-null属性引用null或transient值:xxx.xxx.xxx.domains.PathSections._PathViews_sectionsBackref

这通常是异常的样子,对所涉及的域类有一些变化。更糟糕的是,当发生此错误时,涉及列表的每个其他事务操作都将导致相同的错误(不同的域类),无论是否同时执行。然后需要重新启动服务器以临时修复它。以下是相关域类的一些片段:

class PathViews extends View{

static constraints = {
    molreports(nullable:true)
    molorders(nullable:true)
    otherreports(nullable: true)
    sections(nullable:true)
    addendum(nullable:true)
    images(nullable:true)
    edits(nullable:true)
}

List sections
List otherreports
List molreports
List molorders
List images
PathEdits edits
PathSections addendum
int headings
String accid

static auditable = true

static hasMany = [sections: PathSections, otherreports: PathSections, molorders:MolecularOrder, molreports: MolecularReport, images: PathLocalImage]

static mappedBy = [sections: 'pathviews', otherreports: 'reports']


class PathSections extends Sections {

static constraints = {
    pathviews(nullable:true)
    reports(nullable:true)
}


static auditable = true

static belongsTo =  [pathviews: PathViews, reports: PathViews]

}

我认为最初工作的临时修复是使大多数事务服务方法同步。这似乎只是使错误更随机,更不可重复。我还仔细检查了其他一些事情,例如确保hasMany关系的子对象在添加到父级并使用domainClass.lock(id)而不是domainClass.get(id)之前未显式保存。当只有一个用户使用该应用程序时,根本不会发生此问题。

使用的版本:

  

Grails:2.3.7   Hibernate:3.6.10.10

任何帮助都会非常感激,因为我现在已经接近拔掉我头发上的任何东西,如果需要更多信息,请告诉我。

谢谢! 肖恩。

1 个答案:

答案 0 :(得分:0)

您应该做的第一件事是升级到同一次要版本中的最新版本 - 2.3.11。它不太可能有所帮助,但你可能会很幸运。

集合很棘手,因为它们被认为是拥有域类的属性,但表示为多个数据库记录。所以你有一些有趣的效果,比如无法正确锁定更新实例;给定"作者有很多书",如果你明确地锁定作者实例,结果SQL就像select ... from author for update where id=?。但是你无法锁定这些书籍,如果可以,而且馆藏规模要大得多,你想锁定一百万个馆藏实例吗?因此,您不可避免地会遇到多对多的并发问题,其中子项在顶级实例之间共享,甚至在执行与同步请求重叠的Ajax请求时也是如此。

这只是数据的正确性 - 在GORM中使用集合来保持持久性的潜在性能成本非常高。我在4年前所做的This talk现在和以前一样相关,它展示了1-many和many-many的性能问题,并显示了不使用集合的代码,并且不是&#39受任何这些问题的影响。你必须做更多的工作,但我认为这是一个很小的代价。