Hibernate OneToMany 使用遗留数据库的注释
我正在使用一个根本没有标准化的遗留数据库。他们直接在程序中编码关系(用 Uniface 编写)。现在,他们正在迁移到 Java。遗憾的是,我无法更改数据库,但我需要在表之间映射 OneToMany 关系。
例如,我有一个表 Invoice 和一个表 Item。
表 Invoice 具有这些键。其中前三个用作与 Item 的关系的外键:
invoice_serial_id,
invoice_number_id,
invoice_date,
invoice_otherkey1,
invoice_otherkey2
表 Item 有这些键,前三个与相应的 Invoice 键具有相同的类型和值。
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,例如
@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
如何创建一个使用这个数据库的关系?或者我应该放弃并手动选择项目?
I'm working with a legacy database that isn't normalized at all. They've been coding relationships directly in the program (written in Uniface). Now, they are migrating to Java. Sadly, I can't change the database, but I need to map a OneToMany relationship between tables.
For instance, I have a table Invoice and a table Item.
Table Invoice has these keys. The first three of them are used as foreign keys for the relationship with Item:
invoice_serial_id,
invoice_number_id,
invoice_date,
invoice_otherkey1,
invoice_otherkey2
Table Item has these keys, the first three have the same type and value than their corresponding Invoice keys.
item_serial_id,
item_number_id,
item_date,
item_otherkey1
I have created the tables using reverse engineering from hibernate, which generated Invoice.java, InvoiceId.java, Item.java and ItemId.java, then manually created @OneToMany and @ManyToOne annotations. Here's the code so far:
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;
}
I get the following error:
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
I've also tried following the steps here, and create a @joinTable on Invoice such as
@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")
}
)
but I got 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
How can I create a relationship using this database? Or should I give up and manually select Items?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于时间有限,我没能等到正确的答案。
我最终创建了一个连接示例中这些表的视图,如下所示:
然后我在 Hibernate 中映射了该视图。这对我有用。
Due to time constraints I wasn't able to wait for the right answer.
I ended up creating a view joining those tables in the example, as such:
Then I mapped the view in Hibernate. That's what worked for me.
我认为你需要这样做。
您的发票表有一个带有相应@ID 属性的主键。
发票表中的嵌入 ID 应仅包含项目表中存在的 3 个字段。
创建一个 ItemID 表,映射这三个字段,并在 Invoice 表中引用它。
它会看起来像这样
..............
使用相应的 setter 和 getter,并覆盖 ItemId 类的 hashCode() 和 equals(Object o) 。
目前,您在外键定义中嵌入了 5 个字段,但在 itemID 类中仅强调 3 个字段。您不需要联接表中,您只需创建一个复合键类(包含 3 个字段)并将其嵌入到发票表中。
YI think you need to do this.
Your invoice table has a primary key with corresponding @ID attribute.
The embedded ID in your invoice table should only contain the 3 fields that are present in the Item table.
Create an ItemID table, that mapps these three fields, and reference this in the Invoice table.
it will look like this....
........
with corresponding setters and getters, and overried the hashCode() and equals(Object o) for the ItemId class.
At the moment, you are embedding 5 fields in the foreign key definition, but only stress 3 in your itemID class. You don't need a join table, you are only creating a composite key class (containing the 3 fields) and embedding this in the invoice table.