I've been having an issue with Hibernate 4 that did not happen in Hibernate 3. I'm testing a base dao class which has generic methods for saving, querying, etc.. (not it's not homework). I'm using an embedded derby connection with hibernate.hbm2ddl.auto=create-drop for testing purposes.
EDIT: Fixing cascadeType. Still the same behavior. Even if i add in all the available cascade types from the CascadeType enum, it still fails, unless I put CascadeType.ALL. Not sure what ALL has that you can't specifically enumerate.
In my tests, I have 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 the following sql being executed:
Hibernate:
insert
into
foo_parent
(name, foo_parent_id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
foo_parent_foo
(foo_parent, foo_child)
values
(?, ?)
It seems it's trying to insert into the collection before cascading the save down to the FooChild object.
If i change FooParent to have this:
@OneToMany(cascade={CascadeType.ALL})
The problem goes away.
As i said, this works with hibernate 3, so i'm not sure why it's behaving differently.
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 the Hibernate proprietary operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With