-->
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.  [ 1 post ] 
Author Message
 Post subject: Column index out of range on merge
PostPosted: Fri Mar 18, 2011 10:38 am 
Newbie

Joined: Fri Mar 18, 2011 9:28 am
Posts: 1
Hello.

I'm using Hibernate to map a legacy database with some complicated associations. I need to map a bidirectional @oneToMany association where the @onetoMany is the owner side. So I used the @JoinColumns annotation.

My problem is to use Cascade on this association. When I try to save a new instance it works (using save or merge). But when I remove an item of the collection and need to update the instance I have some problems. I'll post here a small version of the classes (the problem happens with this reduced version too):

Code:
@Table(name="AVORDER")
@Entity
public class Order implements Serializable {
   @EmbeddedId
   private OrderPK pk;
   @Column(name = "DT_SHIPMENT")
   private Date shipmentDate;
   @OneToMany(cascade=CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
   @JoinColumns( {
         @JoinColumn(name = "NR_ID", referencedColumnName = "NR_ID"),
         @JoinColumn(name = "NR_YEAR", referencedColumnName = "NR_YEAR") })
   private List<OrderItem> items;

   //getters and setters...

   @Override
   public boolean equals(Object obj) {
      if (obj == null)
         return false;
      if (this == obj)
         return true;
      if ( obj.getClass() != getClass() )
         return false;
      Order other = (Order) obj;
      return new EqualsBuilder().append(other.getPk(), this.getPk())
            .isEquals();
   }

   @Override
   public int hashCode() {
      return new HashCodeBuilder(13, 21).append(this.getPk()).toHashCode();
   }
}


Code:
@Embeddable
public class OrderPK implements Serializable {
   private static final long serialVersionUID = 1L;
   @Column(name = "NR_ID")
   private Integer id;
   @Column(name = "NR_YEAR")
   private Integer year;

   //getters and setters...

   @Override
   public int hashCode() {
      return new HashCodeBuilder(17, 37).append(year).append(id).toHashCode();
   }

   @Override
   public boolean equals(Object obj) {
      if (obj == null)
         return false;
      if (this == obj)
         return true;
      if (getClass() != obj.getClass())
         return false;
      OrderPK other = (OrderPK) obj;
      return new EqualsBuilder().append(year, other.year).append(id,
            other.id).isEquals();
   }
}


Code:
@Entity
public class OrderItem implements Serializable {
   private static final long serialVersionUID = 1L;
   @EmbeddedId
   private OrderItemPK pk;

   @Column(name = "VL_QTDVOL")
   private Double quantity;

   //getters and setters...

   @Override
   public boolean equals(Object obj) {
      if (obj == null)
         return false;
      if (this == obj)
         return true;
      if (!(obj instanceof OrderItem))
         return false;
      OrderItem other = (OrderItem) obj;
      return new EqualsBuilder().append(this.getPk(), other.getPk())
            .isEquals();
   }

   @Override
   public int hashCode() {
      return new HashCodeBuilder(39, 41).append(this.getPk()).toHashCode();
   }
}


Code:
@Embeddable
public class OrderItemPK implements Serializable {
   private static final long serialVersionUID = 1L;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumns( {
         @JoinColumn(name = "NR_ID", referencedColumnName = "NR_ID", insertable = false, updatable = false, nullable = false),
         @JoinColumn(name = "NR_YEAR", referencedColumnName = "NR_YEAR", insertable = false, updatable = false, nullable = false) })
   private Order order;
   @Column(name = "NR_ITEID")
   private Integer id;

   //getters and setters...

   @Override
   public int hashCode() {
      return new HashCodeBuilder(15, 35).append(order).append(id)
            .toHashCode();
   }

   @Override
   public boolean equals(Object obj) {
      if (obj == null)
         return false;
      if (obj == this)
         return true;
      if (obj.getClass() != this.getClass())
         return false;
      OrderItemPK other = (OrderItemPK) obj;
      return new EqualsBuilder().append(order, other.order).append(id,
            other.id).isEquals();
   }
}


If I try to save, like this:

Code:
   public void saving() {
      OrderPK orderPK = new OrderPK();
      orderPK.setYear(2011);
      orderPK.setId(1);
      
      Order order = new Order();
      order.setPk(orderPK);
      order.setShipmentDate(new Date());
      
      OrderItemPK itemPk = new OrderItemPK();
      itemPk.setId(1);
      itemPk.setOrder(order);
      OrderItem item1 = new OrderItem();
      item1.setQuantity(1d);
      item1.setPk(itemPk);
      
      OrderItemPK itemPk2 = new OrderItemPK();
      itemPk2.setId(2);
      itemPk2.setOrder(order);
      OrderItem item2 = new OrderItem();
      item2.setQuantity(2d);
      item2.setPk(itemPk2);
      
      List<OrderItem> itens = new ArrayList<OrderItem>();
      itens.add(item1);
      itens.add(item2);
      order.setItems(itens);
      
      Transaction tx = session.beginTransaction();      
      session.save(order);      
      tx.commit();
   }


It works. But the next time, when I try to merge the existent instance with another one (with a removed OrderItem), it does not work:

Code:
   public void merging() {
      OrderPK orderPK = new OrderPK();
      orderPK.setYear(2011);
      orderPK.setId(1);
      
      Order order = new Order();
      order.setPk(orderPK);
      order.setShipmentDate(new Date());
      
      OrderItemPK itemPk = new OrderItemPK();
      itemPk.setId(1);
      itemPk.setOrder(order);
      OrderItem item1 = new OrderItem();
      item1.setQuantity(1d);
      item1.setPk(itemPk);
      
      List<OrderItem> itens = new ArrayList<OrderItem>();
      itens.add(item1);
      order.setItems(itens);
      
      Transaction tx = session.beginTransaction();      
      session.merge(order);      
      tx.commit();
   }


The SQL output:

Code:
Hibernate: update AVORDER set DT_SHIPMENT=? where NR_ID=? and NR_YEAR=?
18:59:36,265 TRACE BasicBinder:81 - binding parameter [1] as [TIMESTAMP] - Fri Mar 18 18:59:36 AFT 2011
18:59:36,265 TRACE BasicBinder:81 - binding parameter [2] as [INTEGER] - 1
18:59:36,265 TRACE BasicBinder:81 - binding parameter [3] as [INTEGER] - 2011

...

Hibernate: update OrderItem set NR_ID=null, NR_YEAR=null where NR_ID=? and NR_YEAR=? and NR_ITEID=?
18:59:36,281 TRACE BasicBinder:81 - binding parameter [1] as [INTEGER] - 1
18:59:36,281 TRACE BasicBinder:81 - binding parameter [2] as [INTEGER] - 2011
18:59:36,281 TRACE BasicBinder:81 - binding parameter [3] as [INTEGER] - 2
18:59:36,281 TRACE BasicBinder:81 - binding parameter [4] as [INTEGER] - 1

...

org.postgresql.util.PSQLException: The column index is out of range: 4, number of columns: 3.



First, why Hibernate tries to update OrderItem if I set orphanRemoval to true? Shouldn't it just delete the OrderItem? And why it tries to bind another parameter?

I probably have done something wrong, but I can't figure it out. If I change the referencedColumnNames in the JoinColumns to new ones everything works fine, but hibernate creates new fields (of course) to represent the new fields. I can't do this.

I'm using Hibernate 3.6.0 Final and tried this both with Postgresql 9 and Oracle (not sure about the version).


Thanks in advance, I'm really stuck with this!


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

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.