0

我正在尝试在 GORM 中的 Foo 和 Bar 域之间创建双向的一对多关系。

这是我到目前为止所拥有的:

class Bar {
   static belongsTo = [foo: Foo]
}

class Foo {
   Set bars = []
   static hasMany = [bars: Bar]
}

我遇到的问题是,当我使用关系方法时,它们的行为似乎不像我认为的那样。例如,您会认为像“foo.bars.add(bar)”这样的语句也会在 bar 参数上设置 foo 字段。但是当我调用“bar.foo.id”时,我被告知 foo 字段为空。如果我使用“bar.foo = foo”而不是“foo.bars.add(bar)”,我可以解决这个问题。不幸的是,当我调用“foo.bars.size()”时,它告诉我它是 0。

为了更清楚地了解我在说什么,这是我的测试:

def testFoo() {
   def foo = new Foo()
   def bar = new Bar()

   foo.bars.add(bar)

   println "foo.bars.size() = ${foo.bars.size()}"
   println "bar.id = ${bar.id}"

   for(def xbar : foo.bars) {
      println "bar.id = ${xbar.id}"
   }

   println "foo.id = ${foo.id}"
   println "bar.foo.id = ${bar?.foo?.id}" // <- is null
}

def testBar() {
   def foo = new Foo()
   def bar = new Bar()

   bar.foo = foo

   println "foo.bars.size() = ${foo.bars.size()}" // <- is 0
   println "bar.id = ${bar.id}"

   for(def xbar : foo.bars) {
      println "bar.id = ${xbar.id}"
   }

   println "foo.id = ${foo.id}"
   println "bar.foo.id = ${bar?.foo?.id}"
}

我究竟做错了什么?

注意:我正在通过集成测试运行它。我还发现“foo.addToBars(bar)”的工作方式与我认为“foo.bars.add(bar)”和“bar.foo = foo”应该工作的方式相同。

更新这是我做的一个快速破解(使用 Hibernate 和 JPA):

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;

import stuff.Foo;

public class MyList<Bar> extends LinkedList {

   private Foo foo;

   public MyList(Foo foo) {
      this.foo = foo;
   }

   @Override
   public boolean add(Object obj) {
      boolean result = super.add(obj);

      try {
         Method barMethod = obj.getClass().getDeclaredMethod("setFoo", Foo.class);
         barMethod.invoke(obj, foo);
      }
      catch(NoSuchMethodException noSuchMethod) {
         noSuchMethod.printStackTrace();
      }
      catch(InvocationTargetException invocationTarget) {
         invocationTarget.printStackTrace();
      }
      catch(IllegalAccessException illegalAccess) {
         illegalAccess.printStackTrace();
      }

      return result;
   }
}
4

1 回答 1

2

如果您阅读文档,您将了解到,正如您所发现但仍在质疑的那样,将项目添加到集合以便正确持久化的正确方法是使用这些addTo*方法。

因此,就您而言,当您说使用addToBars有效时,这是正确的方法。也就是说,你会受到一些性能影响。另一种方法是:

bar.foo = foo
bar.save()

缺点是 foo 不会在其现有 Set 中包含 bar。您必须再次从数据库中提取它。这有点让步,你只需根据自己的情况使用最好的方法。

于 2013-10-26T23:27:49.937 回答