2016-08-15 57 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来告诉休眠,它不是一个新对象,而是一个已经保存的对象。