-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Tree (self referencing table) with JPA
PostPosted: Mon Jan 04, 2010 9:58 am 
Newbie

Joined: Mon Dec 25, 2006 5:05 pm
Posts: 5
Hi

I would like to create a mapping, that creates a tree of elements.
sql:
Code:
create table menu(
    id INT unsigned AUTO_INCREMENT not null PRIMARY KEY,
    name varchar(20) not null,
    parent INT unsigned,
    position INT unsigned,
    content TEXT,
    FOREIGN KEY (parent) REFERENCES menu(id)
);


Entity:
Code:
@Entity
@Table(name = "menu")
public class MenuItem{
   
   @Id
   @GeneratedValue
   @Column(name = "id", nullable = false)
   private Long id;
   public Long getId() {
      return id;
   }

   protected void setId(Long id) {
      this.id = id;
   }

   @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
   @IndexColumn(name = "position", base = 1)
   private List<MenuItem> children;
   public List<MenuItem> getChildren() {
      return children;
   }

   public void setChildren(List<MenuItem> children) {
      this.children = children;
   }
   
   @ManyToOne()
   @JoinColumn()
   private MenuItem parent;
   public MenuItem getParent() {
      return parent;
   }

   public void setParent(MenuItem parent) {
      this.parent = parent;
   }
   ...
}


I can delete elements, but if I would like to append one, nothing happens...
@Transactional()
public void append(MenuItem parent, MenuItem child){
parent.addChild(child);
em.persist(parent);
return;
}

I created an element to append, but both parent and position field remains <null>, and I can see only
the insert statement for that element, nothing more.

Code:
    select
        children0_.parent as parent1_,
        children0_.id as id1_,
        children0_.position as position1_,
        children0_.id as id2_0_,
        children0_.content as content2_0_,
        children0_.name as name2_0_,
        children0_.parent as parent2_0_,
        children0_.position as position2_0_
    from
        menu children0_
    where
        children0_.parent=?
[DEBUG,TransactionSynchronizationManager,http-8080-5] Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@1d13f05] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@af0e38] bound to thread [http-8080-5]
[DEBUG,TransactionSynchronizationManager,http-8080-5] Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@1d13f05] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@af0e38] bound to thread [http-8080-5]
Hibernate:
    insert
    into
        menu
        (content, name, parent, position)
    values
        (?, ?, ?, ?)


I use the Spring framework for handling the transactions, and the org.springframework.transaction.annotation.Transactional annotation and Hibernate as JPA provider.

The removal code removes only the actual element, do not update the position of the others:
Code:
   @Transactional()
   public void remove(String id) throws EntityNotFoundException {
      MenuItem item=getPage(id);
      MenuItem parent=item.getParent();
      parent.getChildren().remove(item);
      em.merge(parent);
      em.remove(item);
   }


Any tips?

Thanks:
Bence


Last edited by btakacs on Tue Jan 05, 2010 9:46 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Tree (self referencing table) with JPA
PostPosted: Tue Jan 05, 2010 9:45 am 
Newbie

Joined: Mon Dec 25, 2006 5:05 pm
Posts: 5
Changed the mapping to:
Code:
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
@Cascade( { org.hibernate.annotations.CascadeType.ALL } )
@IndexColumn(name = "position", base = 1)org.hibernate.annotations.CascadeType?
...does not solve anything.

Hibernate does not manage the parent and position after modifiing the PersistentList and persisting the parent object.


Top
 Profile  
 
 Post subject: Re: Tree (self referencing table) with JPA
PostPosted: Wed Jan 06, 2010 11:52 am 
Newbie

Joined: Mon Dec 25, 2006 5:05 pm
Posts: 5
Solved.

This is the mapping that is working now:
Code:
   @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
   @Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN } )
   @IndexColumn(name = "position", base = AppInfo.BASE)
   @JoinColumn(name="parent", nullable=false)
   private List<MenuItem> children;
   public List<MenuItem> getChildren() {
      return children;
   }

   public void setChildren(List<MenuItem> children) {
      this.children = children;
   }
   
   @ManyToOne()
   @JoinColumn(name="parent", insertable=false, updatable=false, nullable=false)
   private MenuItem parent;
   public MenuItem getParent() {
      return parent;
   }


Top
 Profile  
 
 Post subject: Re: Tree (self referencing table) with JPA
PostPosted: Wed Jul 28, 2010 9:12 am 
Newbie

Joined: Wed Jul 28, 2010 8:54 am
Posts: 3
thanks :)

it was really useful for me!


Top
 Profile  
 
 Post subject: Re: Tree (self referencing table) with JPA
PostPosted: Fri Jul 20, 2012 4:09 am 
Newbie

Joined: Tue Jun 17, 2008 11:01 pm
Posts: 16
I think @JoinColumn will not work with inverse=true (mappedby)
Make the One-to-Many side of the relation as the owning side (to make Hibernate manage the index automatically)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.