Hibernate OneToMany с использованием аннотаций с устаревшей базой данных - PullRequest
2 голосов
/ 15 ноября 2011

Я работаю с устаревшей базой данных, которая вообще не нормализована.Они кодируют отношения непосредственно в программе (написано на Uniface).Теперь они мигрируют на Java.К сожалению, я не могу изменить базу данных, но мне нужно отобразить взаимосвязь OneToMany между таблицами.

Например, у меня есть таблица счетов-фактур и таблица Item.

Таблица Счет имеет эти ключи.Первые три из них используются в качестве внешних ключей для связи с Элементом:

invoice_serial_id,  
invoice_number_id,  
invoice_date,
invoice_otherkey1,
invoice_otherkey2  

Таблица Элемент имеет эти ключи, первые три имеют тот же тип и значение, что и их соответствующий Счет-фактураkeys.

item_serial_id,
item_number_id,
item_date,
item_otherkey1

Я создал таблицы, используя обратный инжиниринг из hibernate, который сгенерировал Invoice.java, InvoiceId.java, Item.java и ItemId.java, а затем вручную создал аннотации @OneToMany и @ManyToOne.Вот код на данный момент:

Invoice.java

@Entity
@Table(name = "INVOICE")
public class Invoice implements java.io.Serializable {

    private static final long serialVersionUID = -2073462863929322522L;

    @EmbeddedId
        @AttributeOverrides( {
            @AttributeOverride(name = "invoiceSerialId", column = @Column(name = "INVOICE_SERIAL_ID", nullable = false, length = 9)),
            @AttributeOverride(name = "invoiceNumberId", column = @Column(name = "INVOICE_NUMBER_ID", nullable = false, length = 9)),
            @AttributeOverride(name = "invoiceDate", column = @Column(name = "INVOICE_DATE", nullable = false, length = 7)),
            @AttributeOverride(name = "invoiceOtherkey1", column = @Column(name = "INVOICE_OTHERKEY1", nullable = false, length = 7)),
            @AttributeOverride(name = "invoiceOtherkey2", column = @Column(name = "INVOICE_OTHERKEY2", nullable = false, length = 7))
    })
    private InvoiceId id;

    @OneToMany(mappedBy = "invoice")
    private Set<Item> items;
}

Item.java

@Entity
@Table(name = "ITEM")
public class Item implements java.io.Serializable {
    private static final long serialVersionUID = -2840038244580784867L;

    @EmbeddedId
        @AttributeOverrides( {
            @AttributeOverride(name = "itemSerialId", column = @Column(name = "ITEM_SERIAL_ID", nullable = false, length = 9)),
            @AttributeOverride(name = "itemNumberId", column = @Column(name = "ITEM_NUMBER_ID", nullable = false, length = 9)),
            @AttributeOverride(name = "itemDate", column = @Column(name = "ITEM_DATE", nullable = false, length = 7)),
            @AttributeOverride(name = "itemOtherkey1", column = @Column(name = "ITEM_OTHERKEY1", nullable = false, length = 7))
    })
    private ItemId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
        @JoinColumn(name = "ITEM_SERIAL_ID", referencedColumnName = "INVOICE_SERIAL_ID"),
        @JoinColumn(name = "ITEM_NUMBER_ID", referencedColumnName = "INVOICE_NUMBER_ID"),
        @JoinColumn(name = "ITEM_DATE", referencedColumnName = "INVOICE_DATE")
    })
    private Invoice invoice;
}

Я получаюследующая ошибка:

org.hibernate.AnnotationException: referencedColumnNames(INVOICE_SERIAL_ID, INVOICE_NUMBER_ID, INVOICE_DATE) of com.just.an.stupid.example.app.Item.invoice referencing com.just.an.stupid.example.app.Invoice not mapped to a single property

Я также пытался выполнить шаги здесь и создать @joinTable on Invoice, например

@JoinTable(name = "INVOICE_ITEM",
    joinColumns = {
        @JoinColumn(name = "ITEM_SERIAL_ID", referencedColumnName = "INVOICE_SERIAL_ID"),
        @JoinColumn(name = "ITEM_NUMBER_ID", referencedColumnName = "INVOICE_NUMBER_ID"),
        @JoinColumn(name = "ITEM_DATE", referencedColumnName = "INVOICE_DATE")
    },
    inverseJoinColumns = {
        @JoinColumn(name = "INVOICE_SERIAL_ID", referencedColumnName = "ITEM_SERIAL_ID"),
        @JoinColumn(name = "INVOICE_NUMBER_ID", referencedColumnName = "ITEM_NUMBER_ID"),
        @JoinColumn(name = "INVOICE_DATE", referencedColumnName = "ITEM_DATE")
    }
)

, но я получилthis:

org.hibernate.AnnotationException: A Foreign key refering com.just.an.stupid.example.app.Invoice from com.just.an.stupid.example.app.Item has the wrong number of column. should be 5

Как я могу создать отношения, используя эту базу данных?Или я должен отказаться и вручную выбрать предметы?

Ответы [ 2 ]

1 голос
/ 17 ноября 2011

Из-за нехватки времени я не смог дождаться правильного ответа.

В итоге я создал представление, соединяющее эти таблицы в примере, например:

create or replace table invoice_items as
select distinct
  i.field_1,
  i.field_2,
  i.field_3,
  it.field_4
from
  invoice i
inner join
  item it
on
  (i.invoice_serial_id = it.item_serial_id and
   i.invoice_number_id = it.item_number_id and
   i.invoice_date = it.item_date
  )

Затем я отобразил вид в Hibernate.Вот что сработало для меня.

0 голосов
/ 15 ноября 2011

Y Я думаю, вам нужно это сделать.

  1. Ваша таблица счетов имеет первичный ключ с соответствующим атрибутом @ID.

  2. Встроенный идентификатор в вашей таблице счетов должен содержать только 3 поля, которые присутствуют в таблице Товар.

  3. Создайте таблицу ItemID, которая сопоставляет эти три поля и ссылается на нее в таблице счетов.

это будет выглядеть так ...

@Embeddable
public class ItemId implements java.io.Serializable {

private Long serialNo;
private Long itemNumber;
    private Date itemDate

........ с соответствующими установщиками и получателями, и переопределяет hashCode () и equals (Object o) для класса ItemId.

  1. В вашем счете-фактуре ссылаются на этот ItemId (как вы делаете со встроенным идентификатором и переопределением атрибута.

В данный момент вы встраиваете 5 полей в определение внешнего ключа, но только подчеркиваете 3 в своем классе itemID. Вам не нужна таблица соединений, вы только создаете класс составного ключа (содержащий 3 поля) и встраиваете его в таблицу счетов-фактур.

...