我正在使用一个完全没有规范化的遗留数据库。他们一直在程序中编写关系(用Uniface编写)。现在,他们正在迁移到Java。遗憾的是,我无法更改数据库,但我需要映射表之间的OneToMany关系。
例如,我有一个表Invoice和一个表Item。
表发票包含这些键。前三个用作与Item:
的关系的外键invoice_serial_id,
invoice_number_id,
invoice_date,
invoice_otherkey1,
invoice_otherkey2
表项目包含这些键,前三个键的类型和值与相应的发票键相同。
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
我也尝试过了here步骤,并在Invoice上创建了一个@joinTable,例如
@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")
}
)
但我得到了这个:
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
如何使用此数据库创建关系?或者我应该放弃并手动选择项目?
答案 0 :(得分:1)
由于时间限制,我无法等待正确答案。
我最终在示例中创建了一个连接这些表的视图,如下所示:
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中映射了视图。这对我有用。
答案 1 :(得分:0)
我认为你需要这样做。
您的发票表有一个主键和相应的@ID属性。
发票表中的嵌入式ID应仅包含Item表中的3个字段。
创建一个ItemID表,用于映射这三个字段,并在Invoice表中引用它。
它看起来像这样......
@Embeddable
public class ItemId implements java.io.Serializable {
private Long serialNo;
private Long itemNumber;
private Date itemDate
........ 使用相应的setter和getter,并为ItemId类重写hashCode()和equals(Object o)。
目前,您在外键定义中嵌入了5个字段,但在itemID类中只有3个字段。您不需要连接表,只需创建复合键类(包含3个字段)并将其嵌入发票表中。