Reputation: 736
I have 2 tables, T_PLN and T_PLN_CST_PRD A generator (M2M.Q_PLN_ID) is defined in the database (Oracle) and should be used as the primary key for both tables.
While saving a new plan (which contains a CostPeriod), I want the generator to create a new primary key for T_PLN and use it in T_PLN_CST_PRD as a primary key as well.
Table T_PLN PLN_ID // primary key (long) generated by sequence // some more columns
Table T_PLN_CST_PRD PLN_ID // primary key - should be same one as in T_PLN table // some more columns
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID", table = "T_PLN_CST_PRD")
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
...
}
Code above is missing something to connect both primary keys, but I'm not sure what...
I tried all sorts of relations (@OneToOne with mappedBy, @JoinColumn, adding Plan as a member of T_PLN_CST_PRD..) but couldn't get it to work due to verious reasons:
IdentifierGenerationException: ids for this class must be manually assigned before calling save():
IdentifierGenerationException: attempted to assign id from null one-to-one property
and others...
also tried the solution in: OneToOne between two tables with shared primary key with no luck.
How should this kind of relation be defined?
Upvotes: 0
Views: 1211
Reputation: 23226
Assuming JPA 2+ then you be able to easily map this as below:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL}, mappedBy = "plan")
CostPeriod costPeriod;
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID")
Plan plan;
}
Ensure you have set both sides of the relationship before persisting.
plan.setCostPeriod(costPeriod);
costPeriod.setPlan(plan);
Upvotes: 1
Reputation: 8247
I think your are missing @PrimaryKeyJoinColumn
and MapsId
for a bidirectional one-to-one shared primary key model.
Can you try the following mapping:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@PrimaryKeyJoinColumn
//OR
//Instead of above @OneToOne and @PrimaryKeyJoinColumn use below:
//@OneToOne(mappedBy="plan", cascade = {CascadeType.ALL})
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
@OneToOne
@JoinColumn(name = "id")
@MapsId
private Plan plan;
...
}
And while saving:
Plan p = new Plan();
CostPeriod cp = new CostPeriod();
p.costPeriod = cp;
cp.plan = p;
session.persist(p);
Upvotes: 0