Cascading does not work with Hibernate 4 and @OneToMany

I am having a problem with Hibernate 4 that did not happen in Hibernate 3. I am testing a dao base class that has common methods for saving, querying, etc. (this is not homework). I am using the built-in derby connection with hibernate.hbm2ddl.auto = create-drop for testing purposes.

EDIT: Fix cascadeType. Still, the same behavior. Even if I add all the available cascade types from the CascadeType enumeration, it still fails if I do not put CascadeType.ALL. I'm not sure that EVERYTHING is there, that you cannot specifically list.

In my tests, I have the following mapped classes:

@Entity @Table(name="FOO_CHILD") public class FooChild { @Id @Column(name="FOO_ID") private Long id; @Column(name="NAME") private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @Table(name="FOO_PARENT") public class FooParent { @Id @Column(name="FOO_PARENT_ID") private Long id; @Column(name="NAME") private String name; @Fetch(FetchMode.SELECT) @Type(type="long") @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}) @JoinTable(name="FOO_PARENT_FOO", joinColumns={@JoinColumn(referencedColumnName="FOO_PARENT_ID")}, inverseJoinColumns={@JoinColumn(referencedColumnName="FOO_ID")}) private List<Foo> fooChild; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Foo> getFooChild() { return fooChild; } public void setFooChild(List<Foo> fooChild) { this.fooChild = fooChild; } } 

And then I try to save:

 FooChild fooChild = new FooChild(); fooChild.setId(1L); fooChild.setName("fooChild"); FooParent fooParent = new FooParent(); fooParent.setId(1L); fooParent.setName("fooParent"); fooParent.setFooChild(new ArrayList<FooChild>(Arrays.asList(fooChild))); session.save(fooParent); session.flush(); session.clear(); 

I get the following trace:

 org.hibernate.exception.ConstraintViolationException: INSERT on table 'FOO_PARENT_FOO' caused a violation of foreign key constraint 'FKF18290CAECA19CB8' for key (1). The statement has been rolled back. at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74) ... 

I noticed that the following sql is running:

 Hibernate: insert into foo_parent (name, foo_parent_id) values (?, ?, ?, ?) Hibernate: insert into foo_parent_foo (foo_parent, foo_child) values (?, ?) 

It seems he is trying to insert into the collection before cascading the save to the FooChild object.

If I changed FooParent to this:

 @OneToMany(cascade={CascadeType.ALL}) 

The problem disappears.

As I said, this works with hibernate 3, so I'm not sure why it behaves differently.

+4
source share
1 answer

save() , persist() and merge() are three different operations. If you want to cascade the save() operation, you need to use the Hibernate annotation

 @Cascade(CascadeType.SAVE_UPDATE) 

or

 cascade = CascadeType.ALL 

which also include Hibernate overhead.

+1
source

All Articles