2013-10-26 50 views
0

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

这是我到目前为止有:

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; 
    } 
} 
+0

我尝试了使用Hibernate和JPA的相同“实验”,但得到了相同的结果。 从Java的角度来看,我可以理解持有多个元素的Container不知道如何在关系的另一侧设置值。 (即bar.foo = foo) 但是,从数据库的角度来看,这没有任何意义。当我调用“foo.bars”时,是否也执行SQL查询“SELECT * FROM Bar WHERE foo_id =:foo_id”?如果是这种情况,那么必须设置条对象的foo字段。但事实并非如此。然而,foo.bars包含该栏。 – tygerpatch

回答

2

如果read the documentation,您将了解的是,当你发现了,但仍质疑,将项目添加到集合以正确保持项目的正确方法是使用addTo*方法。

所以在你的情况下,当你说使用addToBars工作,这是正确的方法来做到这一点。这就是说,你有一些性能点击。另一种方法是:

bar.foo = foo 
bar.save() 

缺点是foo在其现有的Set中不包含bar。你必须再次从数据库中取出它。这是一个给予和采取的一点,你只是为你的情况使用最好的方法。

+0

文档在哪里说addTo *方法是将项目添加到集合的正确方法? addTo *的文档只说明它将设置双向关系的两侧。 – tygerpatch

+0

是的,也就是说如果你想双方都设定好,那就是你应该做的。 – Gregg