2013-10-26 51 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