-->
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.  [ 7 posts ] 
Author Message
 Post subject: Reordering items in List throws a constraint violation
PostPosted: Sun Mar 12, 2017 7:44 pm 
Newbie

Joined: Sun Mar 12, 2017 6:44 pm
Posts: 4
I try to let Hibernate manage the order of items in a list. Whenever I remove an item and add it at the end of the list, Hibernate throws an exception. I tried two different databases (MariaDB and HSQLDB) with the according jdbc drivers, but the problem still remains. I extracted the problem and created a basic test case with still the same problem.

My test case consists of two data object classes and one test class:
Code:
@Entity
public class ParentData {
   @Id @GeneratedValue
   long id;

   @OneToMany @OrderColumn( name = "listOrder" )
   List<ChildData> children = new ArrayList<ChildData>();
   
   public List<ChildData> getChildren() {
      return children;
   }

   public String toString() {
      StringBuilder sb = new StringBuilder();
      for( ChildData child: children ) {
         sb.append( child.toString() );
         sb.append( " / " );
      }
      return sb.toString();
   }
}

Code:
@Entity
public class ChildData {
   @Id @GeneratedValue
   long id;

   String childId;

   public ChildData() {
   }

   public ChildData( String id ) {
      childId = id;
   }

   @Override
   public String toString() {
      return childId;
   }
}

Code:
public class HibTest {
   public static void main(String[] args) {
      SessionFactory sessionFactory;
      Session session = null;

      System.out.println(" SETUP HIBERNATE ");
      try {
         Configuration config = new Configuration().configure("/resources/hibernate.cfg.xml");
         sessionFactory = config.buildSessionFactory();
         session = sessionFactory.openSession();
      } catch (Throwable t) {
         System.err.println("Initial SessionFactory creation failed." + t);
         throw new ExceptionInInitializerError(t);
      }

      System.out.println(" CREATE TEST DATA ");
      session.beginTransaction();
      ParentData parent = new ParentData();
      session.save(parent);

      String[] childrenStr = new String[] { "One", "Two", "Three", "Four", "Five" };
      for (String str : childrenStr) {
         ChildData child = new ChildData(str);
         session.save(child);
         parent.getChildren().add(child);
      }
      session.getTransaction().commit();
      
      System.out.println(" MOVE CHILD DATA");
      List<ChildData> children = parent.getChildren();      
      try {
         System.out.println(parent.toString());
         session.beginTransaction();
         ChildData child = children.get(0);
         children.remove(0);
         session.flush();
         children.add(child);
         session.getTransaction().commit();
         System.out.println(parent.toString());
         System.out.println(" !! WORK DONE !!");
      } catch (Exception e) {
         e.printStackTrace();
         System.out.println(" !! ERROR !!");
         if( session.getTransaction().isActive() )
            if( session.getTransaction().getRollbackOnly() )
               session.getTransaction().rollback();
            else
               session.getTransaction().commit();
      }
   }
}


The output (with Hibernate statements) looks like this:
Code:
MOVE CHILD DATA
One / Two / Three / Four / Five /
Hibernate: delete from ParentData_ChildData where ParentData_id=? and listOrder=?
Hibernate: update ParentData_ChildData set children_id=? where ParentData_id=? and listOrder=?
Mär 12, 2017 11:13:26 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: -104, SQLState: 23505
Mär 12, 2017 11:13:26 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: integrity constraint violation: unique constraint or index violation; UK_9TWN3CBE7SO94343AOP2QKCTC table: PARENTDATA_CHILDDATA
Mär 12, 2017 11:13:26 PM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
INFO: HHH000010: On release of batch it still contained JDBC statements
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
   at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
   at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
   at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
   at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1413)
   at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1393)
   at net.upf.hibtest.HibTest.main(HibTest.java:56)


The third line in the output shows me that hibernate tries to set a new children_id at an already existing listOrder position - and so duplicating the children_id, since it is already in use at the previous listOrder position. Instead it should just set the new listOrder positions for the already existing children_ids.
So I think everything would be fine if the line looked something like
Code:
update ParentData_ChildData set  listOrder=? where ParentData_id=? and children_id=?

for each line to be changed. But I have no idea how to tell Hibernate to do it this way.

I read a lot of online documentation and a lot of questions in online forums, but not many people seem to have that problem, so I think I must be doing something fundamentally wrong in the way I define my classes (have seen no problem during my research) or in the way I reorder the items in the list (nearly no examples found on the internet on how to do this in a Hibernate way, so I did what seemed natural to me).

In fact, six years ago someone seemed to have the same problem here in this forum, but unfortunately he did not receive an answer (viewtopic.php?f=1&t=1012610&p=2448639&hilit=ordercolumn#p2448639).
So maybe in the last years somebody has joined this forum who could provide an answer to this?

Would be grateful for any help. Thanks in advance.


Top
 Profile  
 
 Post subject: Re: Reordering items in list - @OrderList
PostPosted: Mon Mar 13, 2017 2:34 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
There's something that missing from your mappings since you should have used an @OrderColumn, right? You can also use the @OrderBy annotation, if you ant to maintain the order in the JvM< and not materialize it in the DB.

Unidirectional bags are very inefficient. Check out this High-Performance Hibernate presentation I gave.

You are better off if you turn this into a bidirectional association, and just make sure that you synchronize both ends of the association. This way, you will not use a join table just to hold the association between the parent and the child.


Top
 Profile  
 
 Post subject: Re: Reordering items in List throws a constraint violation
PostPosted: Mon Mar 13, 2017 4:46 am 
Newbie

Joined: Sun Mar 12, 2017 6:44 pm
Posts: 4
Hi vlad,

thanks for your answer. I will check out your presentation soon - for now I would like to point out that indeed there is an @OrderColumn in the ParentData class:
Code:
@OneToMany @OrderColumn( name = "listOrder" )

The tables that are created in the DB look OK, the test data is filled in correctly, as far as I can see.

I need to persist the order of the list in the database, so I felt that @OrderColumn should be the way to go. Retrieving items in the correct/saved order works fine in my application, but trying to change the order of the items leads to the error I described in my post above.

I am planning to do some non-critical projects in the near future in order to learn more about Hibernate. Since these are my first steps with Hibernate, performance was not really an issue but "ease of use" - and because the access always goes from parent to child, I thought the unidirectional way would be a perfect fit.


Top
 Profile  
 
 Post subject: Re: Reordering items in List throws a constraint violation
PostPosted: Mon Mar 13, 2017 1:33 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
If you have a replicating test case, you should open an issue. It might be a bug.


Top
 Profile  
 
 Post subject: Re: Reordering items in List throws a constraint violation
PostPosted: Wed Mar 22, 2017 7:19 am 
Newbie

Joined: Sun Mar 12, 2017 6:44 pm
Posts: 4
If anybody is interested in this, I opened an issue: https://hibernate.atlassian.net/browse/HHH-11587


Top
 Profile  
 
 Post subject: Re: Reordering items in List throws a constraint violation
PostPosted: Wed Mar 22, 2017 8:39 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Thanks. I added a @Cascade with orphanRemoal too, but the issue still replicates. I added a test case in hibernate-core.

Meanwhile, use a bidirectional association as a workaround.


Top
 Profile  
 
 Post subject: Re: Reordering items in List throws a constraint violation
PostPosted: Wed Mar 22, 2017 1:03 pm 
Newbie

Joined: Sun Mar 12, 2017 6:44 pm
Posts: 4
Thanks for your support, Vlad. :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.