2016-02-15 3 views
0

У меня есть 2 таблицы, T_PLN и T_PLN_CST_PRD Генератор (M2M.Q_PLN_ID) определен в базе данных (Oracle) и должен использоваться как первичный ключ для обеих таблиц.Hibernate: Как установить отношения между двумя таблицами с одним и тем же последовательным сгенерированным первичным ключом?

При сохранении нового плана (который содержит CostPeriod), я хочу, чтобы генератор создавал новый первичный ключ для T_PLN и использовал его в T_PLN_CST_PRD в качестве первичного ключа.

Таблица T_PLN PLN_ID // первичный ключ (длинный), порожденный последовательностью // еще некоторые столбцы

Таблица T_PLN_CST_PRD PLN_ID // первичный ключ - должен быть таким же, как и в один T_PLN таблице // еще немного колонны

@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; 

    ... 
} 

Код выше что-то отсутствует, чтобы соединить обе первичные ключи, но я не уверен, что ...

Я пробовал все виды уплотнительных е отношения (@OneToOne с mappedBy, @JoinColumn, добавляющие план в качестве члена T_PLN_CST_PRD ..), но не мог заставить его работать из-за Verious причин:

  • IdentifierGenerationException: идентификаторы для этого класса должен быть вручную назначается перед вызовом сохранения():

  • IdentifierGenerationException: попытка присвоить идентификатор от нуля один-к-одному свойству

и другие ...

также попытался решить проблему: OneToOne between two tables with shared primary key не повезло.

Как определить такое отношение?

ответ

1

Предполагая JPA 2+, то вы сможете легко отобразить это, как показано ниже:

@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; 
} 

Убедитесь, что перед установкой вы установили обе стороны отношений.

plan.setCostPeriod(costPeriod); 
costPeriod.setPlan(plan); 
+0

Я, хотя он работал, не терпит никаких ошибок и данные сохраняются в базе данных. Но идентификаторы не совпадают. кажется, что для таблиц создаются 2 разных первичных идентификатора. –

+0

сейчас он не работает - жалуется на: «Запрошенный bean-файл в настоящее время находится в создании: есть ли неразрешимая круговая ссылка?» –

+0

Я проверил свое ** оригинальное ** решение против книги ProJPA2, и я не вижу ничего плохого. Отправьте код, в котором вы создаете и сохраняете сущности. Я не вижу, учитывая эти сопоставления, как можно создать CostPeriod с другим идентификатором. Я имею в виду, откуда этот «другой» идентификатор? –

0

Я думаю, что у вас отсутствует @PrimaryKeyJoinColumn и MapsId для двунаправленной модели общего первичного ключа один к одному.

Вы можете попробовать следующее: отображение

@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; 

    ... 
} 

И при сохранении:

 Plan p = new Plan(); 
     CostPeriod cp = new CostPeriod(); 
     p.costPeriod = cp; 
     cp.plan = p; 
     session.persist(p); 
+0

Разве он не хотел бы сопоставления с одной стороны отношений, а не определения столбца объединения с обеих сторон? Кроме того, добавление таблицы = "T_PLN_CST_PRD" не приведет к тому, что столбец соединения будет находиться в T_PLN_CST_PRD. Я считаю, что таблица будет указана только в том случае, если для CostPeriod определен '@ SecondaryTable'. –

+0

@AlanHay Моя ошибка. скопируйте ошибки. Наряду с этим я использовал IDENTITY как стратегию. Мне нравится ваш простой код. Но затем я обновил код. хотел бы услышать любые предложения/комментарии. Кстати, я не получил ваш комментарий относительно SecondaryTable. Можете ли вы уточнить. –

+0

Это будет работать. это провалилось для меня по той же причине, что и в @Alan Hay. (Триггер DB) –

Смежные вопросы