Gilad Shahrabani
Gilad Shahrabani

Reputation: 736

Hibernate: How to set the relations between two tables with the same sequence generated primary key?

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:

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

Answers (2)

Alan Hay
Alan Hay

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

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

Related Questions