为什么Grails / GORM / Hibernate在.save()上击中了我的二传手,以及如何处理它?

时间:2012-01-19 21:07:56

标签: hibernate grails save gorm setter

我有一个包含两个变量的DomainClass,用户只能设置一个或另一个。他们没有设置的那个是由他们设置的那个中的一些代码决定的。因此,如果他们设置了A,B就会设置我想要的东西,如果他们设置了B,A就会得到我想要的东西。我遇到的问题是在.save() GORM或Hibernate上,或者某些东西也在击中设置者。

这是我的示例域添加到名为l2getset的新grails 2.0项目:

package l2getset

class ExampleDomain {
  String thisIsA
  String thisIsB
  void setThisIsA(String thisIsA){
    println "Hitting A Setter"
    this.thisIsA = thisIsA
    this.thisIsB = 'user set A'
  }
  void setThisIsB(String thisIsB){
    println "Hitting B Setter"
    this.thisIsB = thisIsB
    this.thisIsA = 'user set B'
  }
  static constraints = {
  }
}

引导程序:

import l2getset.*
class BootStrap {
  def init = { servletContext ->
    def someExample = new ExampleDomain()
    someExample.thisIsA = "Some String"

    println "Some Example is: ${someExample.thisIsA} / ${someExample.thisIsB}"
    someExample.save()
    println "Some Example is: ${someExample.thisIsA} / ${someExample.thisIsB}"  
  }
  def destroy = {
  }
}

打印:

| Running Grails application
Hitting A Setter
Some Example is: Some String / user set A
Hitting A Setter
Hitting B Setter
Some Example is: user set B / user set A
| Server running. Browse to http://localhost:8080/l2getset

我如何区分何时“合法地”设置其中一个以及何时GORM / Hibernate / PleaseExplain只是“与我的二传手一起玩”才能保留我的东西?

这个问题:Why are setters in Grails called twice on save?似乎也触及了这个问题,但我仍然想知道发生了什么以及如何解决我的问题。

3 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为在加载时设置属性时,hibernate会自动使用setter。你想要的是在hibernate中对这些属性的字段级访问。

请参阅此内容以了解如何实施它。

Grails: field access with GORM

答案 1 :(得分:1)

另一种方法是将值保存在一个值中,但是使用transient属性作为代码与之交互的值。瞬态属性的setter中包含额外的代码,它还设置了hibernate知道的“真实”值。

前:

package l2getset

class ExampleDomain {
  String _thisIsA
  String _thisIsB

  static transients = ["thisIsA", "thisIsB"]

  String getThisIsA() { _thisIsA }

  void setThisIsA(String thisIsA){
    println "Hitting A Setter"
    this._thisIsA = thisIsA
    this._thisIsB = 'user set A'
  }

  String getThisIsB() { _thisIsB }

  void setThisIsB(String thisIsB){
    println "Hitting B Setter"
    this._thisIsB = thisIsB
    this._thisIsA = 'user set B'
  }
}

打印:

Running Grails application..
Hitting A Setter
Some Example is: Some String / user set A
Some Example is: Some String / user set A
Server running. Browse to http://localhost:8080/transient-setter

如果需要,您可以搞乱域类的映射,告诉它_thisIsA_thisIsB字段映射到没有_的文件名。

答案 2 :(得分:0)

这是我的黑客解决方案:

使用以下对堆栈跟踪的检查替换this.thisIsB = 'user set A'中的行void setThisIsA

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
if(!stackTrace.find('DefaultSaveOrUpdateEventListener')){
  this.b = 'user set A'
}

void setThisIsB

反之亦然