views:

11

answers:

1

I have a 1:n relation in the database and java objects that represent the relation with hibernate. The primary key of the parent table is generated with a database sequence, the child object uses the primary key of the parent object as foreign key.

I create a new parent object including a set of new child objects. Then I try to persist all objects with one single

session.save(contract);

The storage of the parent object works without problems, but as soon as I add child objects I get an exception

... not-null property references a null or transient value ...

because of the missing FK in the child object.

Is there a mapping which tells hibernate to use the newly generated PK of the parent object as FK in the child objects, or do I have to persist the child objects separately with the FK manually set?

mapping parent object: ...

@Id 
@Column(name="ID", unique=true, nullable=false, precision=22, scale=0)
@SequenceGenerator(name="sequence_seq", sequenceName="SEQ_CONTRACT")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence_seq")
public long getId() {
    return this.id;
}

...

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="contract")
    public Set<ContractSearchtags> getContractSearchtagses() {
        return this.contractSearchtagses;
    }

...

mapping of child object

...

@ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="CONTRACT_ID", nullable=false)
    public Contract getContract() {
        return this.contract;
    }

...

A: 

Is there a mapping which tells hibernate to use the newly generated PK of the parent object as FK in the child objects, or do I have to persist the child objects separately with the FK manually set?

There is no particular mapping to use for this. However, I suspect that you're not setting "both sides of the link" correctly when building your bidirectional association. You need to do something like this:

Contract contract = new Contract();
...
ContractSearchtags tag = new ContractSearchtags();
...
contract.getContractSearchtagses().add(tag);
tag.setContract(contract);

session.save(contract);

Developers typically use "link management methods" to correctly set both sides (in Contract):

public void addToContractSearchtagses(ContractSearchtags tag) {
    contractSearchtagses.add(tag);
    tag.setContract(this);
}

And then the code becomes:

Contract contract = new Contract();
...
ContractSearchtags tag = new ContractSearchtags();
...
contract.addToContractSearchtagses(tag);

session.save(contract);

Resources

Pascal Thivent

related questions