2
@Entity
@Table(name = "parent")
public final class Parent extends Base {

@OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Person person;

and doing (amongst other things) this :

Parent parent = new Parent();
Person person = new Person();
parent.setPerson(person);
session.save(parent);

I get the mentioned exception ?

Do I manually need to call session.save(person) before ? do I have to add a cascade type annotation to the childs class definition(where it references the parent) ?

Or have I missed something else obvious ?

I don't want to use CascadeType.ALL as when a parent is deleted I want to keep the person(child).

Both entities/tables extend a common Base table :

@MappedSuperclass()
public abstract class Base {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    public Integer getId() {
    return id;
    }

Will this effect which cascade type is required ?

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • Is everything ok with the ID generation of both entities? – TC1 Jan 27 '12 at 12:05
  • there is none until saving, but the child(person) is not being saved, just tried ALL instead of persist and that works... so I think maybe its the onetoone mapping requiring ALL, and not just persist. But I may well be wrong ... – NimChimpsky Jan 27 '12 at 12:09
  • 1
    http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-hibspec-cascade Try `{PERSIST, MERGE}` – TC1 Jan 27 '12 at 12:14
  • 2
    @NimChimpsky - You need CascadeType.MERGE (in addition to the CascadeType.PERSIST you already have). Gobbledegook! Beat by TC1 by a minute. – Perception Jan 27 '12 at 12:15

1 Answers1

6

You haven't mentioned the Hibernate version, but this hasn't changed since I ever started using it.

As you can read in the Hibernate reference, to get the Java standard SAVE_UPDATE you need {CascadeType.PERSIST, CascadeType.MERGE} in Hibernate.

EDIT: Seeing the updated info, what you're doing now causes Hibernate to treat it as a bi-directional one-to-one mapping. This basically means that for each object in any of those two tables, there has got to be a counterpart in the other table with the same ID. Therefore, you cannot delete only one of them, you would lose FK integrity.

If you want it to be a unidirectional mapping, e.g., if you want to be able to delete the person but leave the parent -- you have to specify a FK, usually via @JoinColumn, like @JoinColumn(name="PERSON_ID", unique=false, nullable=true, insertable=true, updatable=true)

TC1
  • 1
  • 3
  • 20
  • 31
  • it has to be hibernate or jpa, ALL is working for me, but merge and persist together are not. I am using hibernate 4 btw. Is the OneToOne mapping causign the issue ? – NimChimpsky Jan 27 '12 at 12:30
  • @NimChimpsky How are the IDs generated? What's on the other end, in the `Person` class? – TC1 Jan 27 '12 at 12:41
  • They are auto generated, neither has an id until succesfulyl being saved. CascadeType.ALL works fine ... but I don't want this, I want child to stay even if parent is deleted. – NimChimpsky Jan 27 '12 at 12:43
  • @NimChimpsky It matters because you can only have `ALL` if Hibernate treats it as a shared PK. You might need to explicitly state a `@JoinColumn` on the person mapping if you want it to be unidirectional. Without seeing how the ID is created (I get that it's generated, that part is obvious -- how is it annotated?) I can't really tell you much more... – TC1 Jan 27 '12 at 12:47
  • I actually want to able to delete the parent and keep the child ... ? – NimChimpsky Jan 27 '12 at 13:23
  • @NimChimpsky Then your mapping's off, you need to turn it around, i.e., `Person` has to contain the `Parent` ref with the cascade. If you want, you can then add a `Person` ref to the `Parent` class either via an inverse join column or in some other way. – TC1 Jan 27 '12 at 13:28