2014-07-21 150 views
1

我最近從Grails 2.2.5升級到2.4.2。升級後,我的很多hasMany關係都沒有保存。hasMany保存不工作Grails 2.4.2升級

例如:

Domains: 
    class Node { 
     String name 
     String description 

     static belongsTo = CustomGlobe 
     static hasMany = [containers: Container] 
    } 

    class Container { 
     String name 
     CustomGlobe customGlobe 

     static belongsTo = Node 
     static hasMany = [nodes: Node] 
    } 

    class CustomGlobe { 
     String name 

     static belongsTo = CustomLocation 
     static hasMany = [customLocations: CustomLocation, nodes: Node] 
    } 

    class CustomLocation { 
     String name 
     String description 
    } 

在執行我添加了@Transactional類DEF上述交易的服務。我還試圖根據Grails 2.4.2: Strange cascading save behaviour in nested transactions添加@Transactional(propagation = Propagation.REQUIRES_NEW)。如果我回滾Grails升級(相同的控制器,服務和視圖代碼),節點集合將被正確保存,但是,對於Grails 2.4.2而言,它不會。我也在保存之前和之後通過打印對象的節點進行了檢查,並且它顯示在控制檯上,但是當我的應用程序重定向到列表視圖時,它不會顯示並且不會在任何地方持久保存。

--UPDATE-- 這仍然發生在Grails 2.4.3 我也相信它可能與連接表有關,但我不明白爲什麼。容器在params綁定後具有附加的節點,但在.save()之後,它不會保留到連接表中。

--UPDATE-- 對不起,域類代碼的帖子中有錯誤,它已被更新,現在是正確的。希望有人能夠闡明我現在想念的東西。

Nodes集合未被持久保存到NODE_CONTAINERS表中的Container實例時發生此問題。

--UPDATE - 問題正在進行中。在調試時,我使用Grails數據源創建了一個新的Groovy Sql實例,並手動將節點插入到NODE_CONTAINERS表中。一切正確保存並在查看容器show gsp時被正確調用。所以看起來,GORM在讀取實例時正確地處理了連接表,仍然不確定爲什麼它沒有正確地將節點保存到連接表中。

應用示例演示的錯誤:

  1. 工作的應用使用Grails 2.2.5(2.2.5分支)以上使用Grails 2.4.3(MASTER分支)描述
  2. 應用表現出錯誤

https://github.com/bwagner5/grailsCollectionsDebugApp/tree/master

Grails的數據粘合劑:

這個問題似乎是Grails數據綁定器。 Spring Data Binder工作正常(在2.2.x中是默認的,你可以在2.3.x中重寫Grails聯編程序,但不能在2.4.x中) 我已經放入了JIRA,但仍然希望看看是否有解決方法現在: https://jira.grails.org/browse/GRAILS-11638

+0

您是否正確升級了所有插件?一些老插件與新的Grails存在錯誤。 – wwarlock

+0

是的,我沒有正確升級。它似乎不喜歡joinTable。如果我在綁定參數數據後打印對象,我可以看到節點的集合,但在保存()後,它們不見了。我檢查了hasErrors,它沒有任何東西。其他一切都正確(名稱和說明)。有什麼想法嗎? –

+0

'Node'有許多'Container','Container'有很多'Node',但'Node'屬於'CustomGlobe',而不是'Container'。那是故意的嗎? –

回答

2

我會推薦實際添加單獨的連接類,這也是Burt Beckwith提出的建議,您會發現這個練習在Grails Spring Security Core項目中使用。例如只用你的節點和容器類,你會最終:

class Node { 
    String name 
    String description 
    Set<NodeContainer> nodeContainers = [] 
    static hasMany = [nodeContainers: NodeContainer] 
} 

class Container { 
    String name 
    CustomGlobe customGlobe 

    //potentially add a helper method for fetching the nodes, but no GORM specification should be made on this class 
} 


class NodeContainer { 
    Container container 
    Node node 

    static NodeContainer addNodeContainer(Node node, Container container){ 
     def n = findByNodeAndContainer(node, container) 
     if(!n){ 
      n = new NodeContainer(container: container) 
      node.addToContainers(n) 
      n.save() 
     } 
    } 

    // Other helper methods such as remove and table mappings if necessary 
} 

這樣,要創建和刪除的連接一次一個,而不是要求的休眠加載整個設置,然後添加/從中刪除項目。你也不需要在這兩個類上都有hasMany,它可以在大集合上具有性能並且可以節省問題。我設法通過實施這種模式來解決我所有的時髦保存問題。祝你好運,我希望這有助於!

+0

有趣的是,我觀看了Burt的視頻,但是我在交易中遇到了一些問題。 r創建,然後是NodeContainer中的節點(因爲容器必須先有一個ID)。在更新容器時,我首先將節點保存到NodeContainer,然後保存容器。如果我通過添加節點進行更新,一切都按預期工作。如果我刪除了節點,我會得到一個具有相同標識符值的不同對象已與該會話相關聯:[NodeContainer ...] –

+0

您需要確保已經在Node和Node上調用了save()容器,然後從它們創建NodeContainer。這可能是你的問題的原因。 – th3morg

1

多對多應該只有一個擁有方。在此基礎上,你將需要一個修改Node域類,並與下面的示例中,連接表得到相應的填充:

// Modification in Node 
// Remove this belongsTo 
// belongsTo should be only in the child side of m-m relationship 
// static belongsTo = CustomGlobe 

然後按照這個樣本(自舉嘗試。常規)看到連接表NODE_CONTAINERS表填充象下面這樣:

def node = new Node(name: "Node1", description: "Desc1") 
def cg = new CustomGlobe(name: "CG1") 

def cl1 = new CustomLocation(name: "CL1", description: "Cust Location 1") 
def cl2 = new CustomLocation(name: "CL2", description: "Cust Location 2") 

[cl1, cl2].each { cg.addToCustomLocations it } 

cg.save() 

def cont1 = new Container(name: "Cont1", customGlobe: cg) 
def cont2 = new Container(name: "Cont2", customGlobe: cg) 

// After removing one of the belongsTo the cascading behavior will not be 
// achieved. So the other side of many-many has to be saved explicitly. 
def node2 = new Node(name: "Node2", description: "Desc2").save() 
def node3 = new Node(name: "Node3", description: "Desc3").save() 
cont2.addToNodes(node2).addToNodes(node3).save() 

[cont1, cont2].each { node.addToContainers it} 

node.save flush: true 

enter image description here

測試Grails的2.4.2 &可以共享示例應用程序,如果還存在一定的問題。

+0

好吧,我改變了關係,但問題仍然存在。 –

+0

你可以在github上分享一個可以看到的最小樣本示例嗎? – dmahapatro

+0

我可以嘗試將裸露的最小應用發佈到github上,需要一些時間。該應用程序是一個大型企業應用程序的一部分,具有很多依賴性(糟糕的龐然大物,我知道:()。因爲我仍在調試此問題,我使用Grails數據源創建了一個新的Sql實例,並手動將節點插入到NODE_CONTAINERS表中,保存正確,並在查看容器show gsp(添加了更新問題)時被召回。也許這會引發一些事情,但我看到我是否可以創建裸機應用程序 –