为什么 Grails/GORM/Hibernate 在 .save() 上击中了我的 setter 以及该怎么办?

发布于 2024-12-27 17:29:01 字数 1571 浏览 2 评论 0原文

我有一个包含两个变量的 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 只是“玩弄我的设置器” “在它坚持我的东西之前?

这个问题: 为什么 Grails 中的 setter 在保存时被调用两次?< /a> 似乎也触及了这个问题,但我仍然想知道发生了什么以及如何解决我的问题。

I have a DomainClass with two variables and the user can only set one or the other. The one they don't set is determined by some code in the setter of the one they set. So if they set A, B gets set what I want, and if they set B, A gets set what I want. The problem I'm having is that on .save() GORM or Hibernate or something is hitting the setters as well.

Here is my example domain added to a fresh grails 2.0 project called l2getset:

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 = {
  }
}

And the bootstrap:

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 = {
  }
}

Prints:

| 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

How do I differentiate between when I "legitimately" set one of these and when GORM/Hibernate/PleaseExplain is just "playing around with my setters" before it persists my stuff?

This question: Why are setters in Grails called twice on save? appears to also touch on the issue, but I'm still left wondering what is going on and how to tackle my problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自由范儿 2025-01-03 17:29:02

另一种方法是将值保留在一个值中,但使用瞬态属性作为代码交互的值。瞬态属性的设置器中有额外的代码,它还设置 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'
  }
}

prints:

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 字段映射到不带 < 的文件名代码>_。

Another way to do this is to have the value be persisted in one value, but you use a transient property as the value that your code interacts with. The setter for the transient property has your extra code in it, and it also sets the "real" value that hibernate is aware of.

Ex:

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'
  }
}

prints:

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

If you need to, you can mess with the mapping of the domain class to tell it that the _thisIsA and _thisIsB fields map to a file name without the _.

温柔戏命师 2025-01-03 17:29:02

这是我的黑客解决方案:

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

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

反之亦然 <代码>无效setThisIsB

Here is my hack solution:

Replace the line this.thisIsB = 'user set A' in void setThisIsA with the following check of the stack trace:

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

And do vice versa for void setThisIsB

岛歌少女 2025-01-03 17:29:01

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

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

Grails:使用 GORM 进行现场访问

It's happening because hibernate automatically uses setters when setting properties when you load. What you want is field-level access to these properties in hibernate.

See this for how to implement it.

Grails: field access with GORM

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文