0

The database table structure is the following:

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

Here is the entity

@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 ...
}

In the very beginning there is only one entity:

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

This entity is fetched in the beginning of program and assigned to another class

Later this class performs addition of new Category as a child to existing root (the one that was fetched in the beginning) property

Addition of child is done like this:

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();

After this instead of expected result in database:

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

I get the following result

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'))

Notes:

  • New Session is created for each action and this session is acquired via Singleton SessionFactory
  • If I refresh() root entity before adding a child -- everything is OK, no duplicates
  • If I perform child addition immediately after fetching root entity -- no duplicates

What could be the reason of this behavior (assuming two different sessions)? And how can it be fixed?

2 Answers 2

1

After fetching from db at the beginning of your program, rootCategory becomes a detached object.

Later when you want to use it in another session, you need to reattach it to this session. Instead of session.save(), you can use session.update()

this.rootCategory.addChild(child);
Transaction tx = session.beginTransaction();
session.update(this.rootCategory);
tx.commit();
session.close();
Sign up to request clarification or add additional context in comments.

Comments

1

If you are closing the session after fetching rootCategory then the rootCategory object becomes a detached object according to the hibernate lifecycle and using Session.save() on it will create a new row for it. Therefore you either need to fetch, add the child and save the rootCategory object in the same session or use refresh to tell hibernate that it is not a new object but one that is already saved.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.