brakebg
brakebg

Reputation: 414

One to many map in Hibernate - error

can anyone tell me where is the error in this example

@Entity
@Table(name = "ITEM")
public class Item  implements Serializable
{

@Id
@GeneratedValue
@Column(name = "ID")
private Long id;

@Column(name = "NAME")
private String name;

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "ID_ITEM",referencedColumnName="ID")
private List<ItemDetail> itemDetails;

second class

 @Entity
    @Table(name = "ITEM_DETAIL")
    public class ItemDetail  implements Serializable
    {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "ID_ITEM")
    private Long itemId;

and the db

COMMIT;

CREATE TABLE item(
id serial PRIMARY KEY,
name VARCHAR(16)
);
CREATE TABLE item_detail(
ID serial PRIMARY KEY,
NAME VARCHAR(16),
ID_ITEM serial REFERENCES item (id)
);

COMMIT;

The error i got is

Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into ITEM (NAME, ID) values (?, ?)
Hibernate: insert into ITEM_DETAIL (ITEM_ID, NAME, ID) values (?, ?, ?)
Hibernate: insert into ITEM_DETAIL (ITEM_ID, NAME, ID) values (?, ?, ?)
Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
    at com.mkyong.common.App.main(App.java:51)
    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:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into ITEM_DETAIL (ITEM_ID, NAME, ID) values (NULL, id1, 161) was aborted.  Call getNextException to see the cause.
    at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2530)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1317)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:350)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2592)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 13 more

Process finished with exit code 1

It's obviously that item_id is null but why??

Thanks Regards

Upvotes: 0

Views: 3009

Answers (3)

Nicolae Albu
Nicolae Albu

Reputation: 1245

Use nullable = false to tell Hibernate that the join column cannot be null:

@Entity
@Table(name = "ITEM")
public class Item  implements Serializable {

    // ...

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "ID_ITEM", referencedColumnName = "ID", nullable = false)
    private List<ItemDetail> itemDetails;

    // ...
}

and remove the itemId property from ItemDetail as it is already mapped by the @JoinColumn annotation. If you need the itemId, then use a bi-directional relationship (hold a reference to the entire Item object, not just the ID).

Upvotes: 1

Don Roby
Don Roby

Reputation: 41165

Having ITEM_ID mapped as a column in ItemDetail is a bit odd, and mapping it that way might might be the source of the problem. Nothing is telling the ItemDetail class that that field should be populated with a proper id for the parent Item, including that it shouldn't be null.

If the detail doesn't need to know about the parent, you might be able to just omit that field in the ItemDetail java code altogether. The field in the table should be populated as a consequence of the relation.

It's more common to map this sort of thing as a bidirectional association, so that you have a @OneToMany relation of Item to ItemDetail and a @ManyToOne relation of ItemDetail to Item, and the relations can be navigated in Java. If the ItemDetail does need to know about the parent item, you should do it this way.

This is described somewhere in the Hibernate Annotations Reference section on mapping associations.

Upvotes: 1

Asad Rasheed
Asad Rasheed

Reputation: 518

@backebg: can you check your db script and let us know that you executed exactly same in Database. If yes then either correct your entities to use "ID_ITEM" or item_detail table to use 'ITEM_ID' instead 'ID_ITEM'. thanks

Upvotes: 1

Related Questions