0
votes

I am looking into Hibernate and storing collections of complex types. But I run into exception.

I have the following persistent class:

public class Item {

    private Long id;
    private Set images = new HashSet();
    private Collection<Data> data = new ArrayList<Data>();

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Set getImages() {
        return images;
    }
    public void setImages(Set images) {
        this.images = images;
    }
    public Collection<Data> getData() {
        return data;
    }
    public void setData(Collection<Data> data) {
        this.data = data;
    }
}

The Data class is as follows:

public class Data {

  private String firstName;
  private String lastName;
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;     
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  @Override
   public boolean equals(Object obj) {
    if(!(obj instanceof Data) )
        return false;
    Data d = (Data) obj;
    if(d.firstName.equals(firstName) && d.lastName.equals(lastName))
        return true;
    return false;
  }
 @Override
 public int hashCode() {
    int result;
    result = 17;
    result = 31 * result + firstName.hashCode();
    result = 31 * result + lastName.hashCode();
    return result;
}

The mapping files are as follows:
For Item class:

<hibernate-mapping>
    <class name="com.entities.Item" table="ITEM">
        <id name="id" type="java.lang.Long">
            <column name="ID" />
            <generator class="identity" />
        </id>
        <set name="images" table="ITEM_IMAGE" inverse="false" lazy="true">
            <key>
                <column name="ID" />
            </key>
            <element type="string">
                <column name="IMAGES" />
            </element>
        </set>
        <bag name="data" table="DATA" inverse="false" lazy="true">
            <key>
                <column name="ID" />
            </key>
            <one-to-many class="com.entities.Data" />
        </bag>
    </class>
</hibernate-mapping>

For Data class:

<hibernate-mapping>
    <class name="com.entities.Data" table="DATA">    
        <id name="firstName" type="java.lang.String">
            <column name="FIRSTNAME" />
            <generator class="assigned" />
        </id>
        <property name="lastName" type="java.lang.String">
            <column name="LASTNAME" />
        </property>
    </class>
</hibernate-mapping>

In my code to save data to MySQL:

Transaction tx = session.beginTransaction();
Item item = new Item();
Set images = new HashSet();
images.add("C:\\");
images.add("D:\\");
item.setImages(images);
List<Data> data = new ArrayList<Data>();
Data a = new Data();
a.setFirstName("John");
a.setLastName("Smith");
data.add(a);
item.setData(data);
session.save(item);
tx.commit();//-->Exception here
session.close();

I get the following exception on tx.commit();

Hibernate: insert into ITEM values ( ) Hibernate: insert into ITEM_IMAGE (ID, IMAGES) values (?, ?) Hibernate: insert into ITEM_IMAGE (ID, IMAGES) values (?, ?) Hibernate: update DATA set ID=? where FIRSTNAME=? Hibernate: update DATA set ID=? where FIRSTNAME=? 1454 [main] ERROR org.hibernate.jdbc.AbstractBatcher - Exception executing batch: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133) at com.entities.Main.main(Main.java:44)

Why do I get this exception?
If I remove the Collection<Data> data to store only the Set the code works and the data are saved in MySQL.

Note: The mapping files have been created by Eclipse Hibernate plugin.

2

2 Answers

1
votes

Made the following changes to your code :

Transaction tx = session.beginTransaction();
Item item = new Item();
//added save here to attach the object to persistance context.
// (This might be optional)
session.save(item);              

Set images = new HashSet();
images.add("C:\\");
images.add("D:\\");
item.setImages(images);           
List<Data> data = new ArrayList<Data>();
Data a = new Data();
a.setFirstName("John");
a.setLastName("Smith");
//added save here to attach the object to persistance context.
//this is required without cascading settings
session.save(a)                 

data.add(a);
item.setData(data);
session.save(item);
tx.commit();//-->Exception here
session.close();

You could otherwise set appropriate the cascading options on the bag!

AFAIK you are getting the error since you are trying to persist an association without the other entity (Data) being in persistant state and the cascading options are set to none by default. Again I haven't tried out to run my piece of snippet but this will point you in the right direction.


UPDATE from the OP:

The problem is solved by using inverse="true", doing cascade and also I have to reference from Data to Item otherwise the FK column is not updated

0
votes

Is it possibly due to the fact that you're adding a to the list data twice?