Hi, the following classes got reverse enginered from my simplified
testcase database with hibernate-tools from cvs last week.
Code:
create table CONTAINER (
SPECIALID INT4 not null,
CONTAINERID INT4 not null,
ITEMID VARCHAR(20) null,
constraint PK_CONTAINER primary key (SPECIALID, CONTAINERID)
);
create table ITEM (
ITEMID VARCHAR(20) not null,
SPECIALID INT4 not null,
constraint PK_ITEM primary key (ITEMID, SPECIALID)
);
create table SPECIAL (
SPECIALID INT4 not null,
constraint PK_SPECIAL primary key (SPECIALID)
);
alter table CONTAINER
add constraint FK_CONTAINE_REFERENCE_ITEM foreign key (ITEMID, SPECIALID)
references ITEM (ITEMID, SPECIALID)
on delete restrict on update restrict;
alter table ITEM
add constraint FK_ITEM_REFERENCE_SPECIAL foreign key (SPECIALID)
references SPECIAL (SPECIALID)
on delete restrict on update restrict;
When trying to persist a created graph, hibernate tries to persist
container with insert into Container (specialid, containerid) values (3, 9)
which fails because of the missing itemid.
However the debug output shows that the item was correctly initialized (IMHO)
Code:
DEBUG org.hibernate.pretty.Printer - Container{item=Item#component[specialid,itemid]{specialid=3, itemid=item1},
Sorry for the many classes (and their odd naming) I was not able to reduce the problem further.
Thank you very much for your input.
Hibernate version: 3.1.1
Code:
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
@Entity
public class Container implements java.io.Serializable {
private ContainerId id;
private Item item;
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name="specialid", column=@Column(name="specialid", unique=false, nullable=false, insertable=true, updatable=true) ),
@AttributeOverride(name="containerid", column=@Column(name="containerid", unique=false, nullable=false, insertable=true, updatable=true) ) } )
public ContainerId getId() {
return this.id;
}
public void setId(ContainerId id) {
this.id = id;
}
@ManyToOne(cascade={},
fetch=FetchType.LAZY)
@JoinColumns( {
@JoinColumn(name="itemid", unique=false, nullable=false, insertable=false, updatable=false),
@JoinColumn(name="specialid", unique=false, nullable=false, insertable=false, updatable=false) } )
public Item getItem() {
return this.item;
}
public void setItem(Item item) {
this.item = item;
}
}
Code:
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable
public class ContainerId implements java.io.Serializable {
private int specialid;
private int containerid;
@Column(name="specialid", unique=false, nullable=false, insertable=true, updatable=true)
public int getSpecialid() {
return this.specialid;
}
public void setSpecialid(int specialid) {
this.specialid = specialid;
}
@Column(name="containerid", unique=false, nullable=false, insertable=true, updatable=true)
public int getContainerid() {
return this.containerid;
}
public void setContainerid(int containerid) {
this.containerid = containerid;
}
}
Code:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
@Entity
public class Item implements java.io.Serializable {
private ItemId id;
private Special special;
private Set<Container> containers = new HashSet<Container>(0);
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name="itemid", column=@Column(name="itemid", unique=false, nullable=false, insertable=true, updatable=true, length=20) ),
@AttributeOverride(name="specialid", column=@Column(name="specialid", unique=false, nullable=false, insertable=true, updatable=true) ) } )
public ItemId getId() {
return this.id;
}
public void setId(ItemId id) {
this.id = id;
}
@ManyToOne(cascade={},
fetch=FetchType.LAZY)
@JoinColumn(name="specialid", unique=false, nullable=false, insertable=false, updatable=false)
public Special getSpecial() {
return this.special;
}
public void setSpecial(Special special) {
this.special = special;
}
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="item")
public Set<Container> getContainers() {
return this.containers;
}
public void setContainers(Set<Container> containers) {
this.containers = containers;
}
}
Code:
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable
public class ItemId implements java.io.Serializable {
private String itemid;
private int specialid;
@Column(name="itemid", unique=false, nullable=false, insertable=true, updatable=true, length=20)
public String getItemid() {
return this.itemid;
}
public void setItemid(String itemid) {
this.itemid = itemid;
}
@Column(name="specialid", unique=false, nullable=false, insertable=true, updatable=true)
public int getSpecialid() {
return this.specialid;
}
public void setSpecialid(int specialid) {
this.specialid = specialid;
}
}
Code:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Special implements java.io.Serializable {
private int specialid;
private Set<Item> items = new HashSet<Item>(0);
@Id
@Column(name="specialid", unique=true, nullable=false, insertable=true, updatable=true)
public int getSpecialid() {
return this.specialid;
}
public void setSpecialid(int specialid) {
this.specialid = specialid;
}
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="special")
public Set<Item> getItems() {
return this.items;
}
public void setItems(Set<Item> items) {
this.items = items;
}
}
Code between sessionFactory.openSession() and session.close():Code:
Special spec = new Special();
spec.setSpecialid(3);
ItemId iid = new ItemId();
iid.setItemid("item1");
iid.setSpecialid(3);
Item item = new Item();
item.setId(iid);
Set<Item> items = new HashSet<Item>();
items.add(item);
spec.setItems(items);
Container cont = new Container();
ContainerId contId = new ContainerId();
contId.setContainerid(9);
contId.setSpecialid(3);
cont.setId(contId);
cont.setItem(item);
Set<Container> containers = new HashSet<Container>();
item.setContainers(containers);
containers.add(cont);
session.save(spec);
session.save(item);
Name and version of the database you are using:postgresql 8.1
Full stack trace of any exception that occurs:Debug level Hibernate log excerpt:Code:
1840 [main] DEBUG org.hibernate.pretty.Printer - listing entities:
1841 [main] DEBUG org.hibernate.pretty.Printer - Container{item=Item#component[specialid,itemid]{specialid=3, itemid=item1}, id=component[specialid,containerid]{containerid=9, specialid=3}}
1841 [main] DEBUG org.hibernate.pretty.Printer - Item{special=null, containers=[Container#component[specialid,containerid]{containerid=9, specialid=3}], id=component[specialid,itemid]{specialid=3, itemid=item1}}
1841 [main] DEBUG org.hibernate.pretty.Printer - Special{items=[Item#component[specialid,itemid]{specialid=3, itemid=item1}], specialid=3}
1841 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener - executing flush
1842 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Inserting entity: [Special#3]
1842 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
1842 [main] DEBUG org.hibernate.SQL - insert into Special (specialid) values (?)
Hibernate: insert into Special (specialid) values (?)
1842 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
1842 [main] DEBUG org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1006)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at Main.main(Main.java:36)
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into Container (specialid, containerid) values (3, 9) was aborted. Call getNextException to see the cause.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2478)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1298)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:347)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2540)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
... 8 more
org.hibernate.persister.entity.AbstractEntityPersister - Dehydrating entity: [Special#3]
1842 [main] DEBUG org.hibernate.type.IntegerType - binding '3' to parameter: 1
1842 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Adding to batch
1842 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Inserting entity: [Item#component[specialid,itemid]{specialid=3, itemid=item1}]
1842 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1
1846 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
1846 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - closing statement
1846 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
1846 [main] DEBUG org.hibernate.SQL - insert into Item (specialid, itemid) values (?, ?)
Hibernate: insert into Item (specialid, itemid) values (?, ?)
1846 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
1846 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Dehydrating entity: [Item#component[specialid,itemid]{specialid=3, itemid=item1}]
1846 [main] DEBUG org.hibernate.type.IntegerType - binding '3' to parameter: 1
1846 [main] DEBUG org.hibernate.type.StringType - binding 'item1' to parameter: 2
1847 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Adding to batch
1847 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Inserting entity: [Container#component[specialid,containerid]{containerid=9, specialid=3}]
1847 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1
1848 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
1848 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - closing statement
1848 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
1848 [main] DEBUG org.hibernate.SQL - insert into Container (specialid, containerid) values (?, ?)
Hibernate: insert into Container (specialid, containerid) values (?, ?)
1848 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
1849 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Dehydrating entity: [Container#component[specialid,containerid]{containerid=9, specialid=3}]
1849 [main] DEBUG org.hibernate.type.IntegerType - binding '3' to parameter: 1
1849 [main] DEBUG org.hibernate.type.IntegerType - binding '9' to parameter: 2
1849 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Adding to batch
1849 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1
1856 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
1856 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - closing statement
1858 [main] DEBUG org.hibernate.util.JDBCExceptionReporter - Could not execute JDBC batch update [insert into Container (specialid, containerid) values (?, ?)]
java.sql.BatchUpdateException: Batch entry 0 insert into Container (specialid, containerid) values (3, 9) was aborted. Call getNextException to see the cause.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2478)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1298)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:347)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2540)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1006)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at Main.main(Main.java:36)
1858 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: null
1858 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Batch entry 0 insert into Container (specialid, containerid) values (3, 9) was aborted. Call getNextException to see the cause.
1858 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 23502
1858 [main] ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: null value in column "itemid" violates not-null constraint
1859 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1006)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at Main.main(Main.java:36)
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into Container (specialid, containerid) values (3, 9) was aborted. Call getNextException to see the cause.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2478)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1298)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:347)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2540)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
... 8 more