Hi everyone,
I am trying currently trying to map a bidirectional one-to-many association between Image and Book class. In fact, Image class has a book attribute (type = Book) that can be null. It is the book the image is in. One given image can be in at most one book. Book has a images attribute (type = Collection) which contains all images contained in the book. I set up the "cascade=all" attribute in order to save all images contained in a book when I save the book.
The problem is the following : when I run my unit test class, I get a NonUniqueObjectException. I have visited Hibernate's website in order to find solutions, but none worked. Can someone tell me what is wrong in my code, my mapping or even my test class ? Thanks in advance :)
Here are parts of my Java code:
/* Class eg.Book */
private Collection images;
private long databaseId;
public void setImages(Collection images) {
this.images = images;
Iterator i = images.iterator();
while (i.hasNext()) {
Image img = (Image) i.next();
img.setBook(this);
}
}
/* Class eg.Image */
private Book book;
private long databaseId;
/* Class eg.storage.impl.HibernateStorageManager */
public class HibernateStorageManager implements BookStorageManager {
[...]
public void store(Book book) throws StorageException {
try {
Session session = getFactory().openSession();
Transaction t = session.beginTransaction();
session.saveOrUpdate(book);
session.flush();
t.commit();
if (session != null) {
session.close();
}
} catch (HibernateException he) {
throw new StorageException(he);
}
}
}
/* Unit testing */
public void testStore() {
Collection c = new ArrayList();
Image[] images = new Image[10];
for (int i = 0; i < 10; i++) {
images[i] = new Image(i + ".jpg");
c.add(images[i]);
}
Book b = new Book();
b.setImages(c);
BookStorageManager.getInstance().store(b);
}
Hibernate version:
2.1.4-patched
Mapping documents:
<hibernate-mapping>
<class name="eg.Image" table="Image">
<id name="databaseId" column="id" type="long" unsaved-value="0">
<generator class="native"/>
</id>
<property name="reference" column="reference" type="string" length="18" not-null="true"/>
<property name="status" column="status" type="int" not-null="true"/>
<property name="receptionDate" column="receptionDate" type="timestamp" not-null="true" />
<property name="originalText" column="originalText" type="text"/>
<property name="message" column="message" type="text"/>
<property name="bookPage" column="bookPage" type="int"/>
<property name="originalImageContentId" column="originalImageContentId"
type="string" length="255" />
<many-to-one name="book" column="bookId" class="eg.Book" not-null="false"/>
</class>
<class name="eg.Book" table="Book">
<id name="databaseId" column="id" type="long" unsaved-value="0">
<generator class="native"/>
</id>
<property name="fileId" column="fileId" type="string" length="255" not-null="true"/>
<property name="status" column="status" type="int" not-null="true"/>
<property name="sentToPrinterDate" column="sentToPrinterDate" type="timestamp" not-null="false" />
<bag name="images" inverse="true" cascade="all">
<key column="bookId"/>
<one-to-many class="eg.Image"/>
</bag>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
Transaction t = session.beginTransaction();
session.saveOrUpdate(book);
session.flush();
t.commit();
Full stack trace of any exception that occurs:
eg.storage.StorageException: hibernate exception
at eg.storage.impl.HibernateStorageManager.store(HibernateStorageManager.java:479)
at eg.storage.BookStorageManagerTest.testStore(BookStorageManagerTest.java:137)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at junit.textui.TestRunner.doRun(TestRunner.java:109)
at junit.textui.TestRunner.run(TestRunner.java:72)
at junit.textui.TestRunner.run(TestRunner.java:57)
at eg.storage.BookStorageManagerTest.main(AggregateStorageManagerTest.java:49)
Caused by: net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1, of class: eg.Image
at net.sf.hibernate.impl.SessionImpl.checkUniqueness(SessionImpl.java:1674)
at net.sf.hibernate.impl.SessionImpl.doUpdateMutable(SessionImpl.java:1443)
at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1470)
at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1393)
at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:114)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:436)
at net.sf.hibernate.engine.Cascades.cascadeCollection(Cascades.java:526)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:452)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:503)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:482)
at net.sf.hibernate.impl.SessionImpl.preFlushEntities(SessionImpl.java:2670)
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2247)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236)
at eg.storage.impl.HibernateStorageManager.store(HibernateStorageManager.java:473)
Name and version of the database you are using:
MySQL 3.23.58
The generated SQL (show_sql=true):
create table Image (
id BIGINT NOT NULL AUTO_INCREMENT,
reference VARCHAR(18) not null,
status INTEGER not null,
receptionDate DATETIME not null,
originalText TEXT,
message TEXT,
bookPage INTEGER,
originalImageContentId VARCHAR(255),
bookId BIGINT,
primary key (id)
);
create table Book (
id BIGINT NOT NULL AUTO_INCREMENT,
fileId VARCHAR(255) not null,
status INTEGER not null,
sentToPrinterDate DATETIME,
primary key (id)
);
alter table Image add index FK310027D03228933A (bookId), add constraint
FK310027D03228933A foreign key (bookId) references Book (id);
|