2016-08-15 7 views
0

Структура таблицы базы данных заключается в следующем:Hibernate дубликатов запись на топка с детьми

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 создается для каждого действия и эта сессия приобретается через Singleton SessionFactory
  • Если я refresh() корневого объекта перед добавлением ребенка - все не в порядке, не дублирует
  • Если я выполняю добавление ребенка сразу после получения корневой сущности - нет дубликатов

Что может быть причиной такого поведения (при условии двух разных сеансов)? И как это можно исправить?

Спасибо.

ответ

1

После извлечения из db в начале вашей программы rootCategory становится отдельным объектом.

Позже, когда вы хотите использовать его в другом сеансе, вам необходимо подключить его к этой сессии. Вместо session.save() вы можете использовать session.update()

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

Если вы закрываете сеанс после извлечения rootCategory, тогда объект rootCategory становится отдельным объектом в соответствии с жизненным циклом гибернации и с помощью Session.save() будет создавать для него новую строку. Поэтому вам нужно либо получить, добавить ребенка и сохранить объект rootCategory в том же сеансе, либо использовать обновление, чтобы сообщить hibernate, что это не новый объект, а тот, который уже сохранен.

Смежные вопросы