2016-08-15 102 views
0

插入記錄的數據庫表結構如下:休眠dublicates與兒童

id  INT 
extId  VARCHAR 
name  VARCHAR 
parent INT (references self.id) 

這裏是實體

@Entity 
@Table(name = "categories") 
public class Category 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id") 
    private int id; 

    @ManyToOne 
    @JoinColumn(name = "parent", referencedColumnName = "id") 
    private Category parent; 

    @org.hibernate.annotations.OrderBy(clause = "name ASC") 
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.ALL) 
    private Set<Category> children = new HashSet<>(); 

    @Column(name = "extId") 
    private String extId; 

    @Column(name = "name") 
    private String name; 

    public void addChild(Category child) 
    { 
     child.setParent(this); 
     this.children.add(child); 
    } 

    //getters and setters ... 
} 

在最開始就只有一個實體:

{ 
    id: 0 
    extId: '' 
    name: 'Category' 
    parent: null 
    children: Set<Category>{/*empty*/} 
} 

該實體在程序開始時被提取並分配給另一個類

後來這個類進行添加新Category作爲一個孩子現有的根

孩子的加入像這樣做(一說是在開始獲取)物業:

Session session = HibernateSessionFactory.getInstance().getFactory().openSession(); 
//gather data 
Category child = new Category(); 
//set name 
//set extId 

this.rootCategory.addChild(child); 

Transaction tx = session.beginTransaction(); 
session.save(this.rootCategory); 
tx.commit(); 
session.close(); 

在此之後而不是預期的結果數據庫:

Root(id(0), extId(''), parent(null), name('root')) 
\-— Child(id(10), extId('art-0'), parent(0), name('child')) 

我得到以下結果

Root(id(0), extId(''), parent(null), name('root')); 
Root(id(10), extId(''), parent(null), name('root')) 
\-— Child(id(11), extId('art-0'), parent(10), name('child')) 

注:

  • Session爲每個操作創建和本次會議通過辛格爾頓獲得SessionFactory
  • 如果我加入了一個孩子之前refresh()根實體 - 一切正常,沒有重複
  • 如果我在取得根實體後立即執行子添加 - 無重複

這種行爲的原因是什麼(假設兩個不同的會話)?如何解決它?

謝謝。

回答

1

在程序開始時從數據庫中讀取數據後,rootCategory成爲分離的對象。

以後,如果您想在另一個會話中使用它,則需要將其重新連接到此會話。代替session.save(),您可以使用session.update()

this.rootCategory.addChild(child); 
Transaction tx = session.beginTransaction(); 
session.update(this.rootCategory); 
tx.commit(); 
session.close(); 
1

如果您在獲取rootCategory後關閉會話,那麼根據hibernate生命週期,rootCategory對象將成爲分離對象,並且使用Session.save()將爲其創建一個新行。因此,您需要獲取,添加子項並將rootCategory對象保存在同一個會話中,或者使用refresh來告訴休眠,它不是一個新對象,而是一個已經保存的對象。