我正在使用Hibernate。
比如说,一个Person
只能有一个Book
。但每个Book
可以由多个Person
s保留。
我正在实现这种关系,并且我正在为这种关系使用一个联合表*person_book*。
以下是我所做的:
Person
类:
@Entity
@Table(name = "person")
public class Person {
private int pid;
private Book book;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinTable(name="person_book",
joinColumns={@JoinColumn(name="pid")},
inverseJoinColumns={@JoinColumn(name="bid")})
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
//Setter & Getter for pid
...
}
Book
类:
@Entity
@Table(name = "book")
public class Book {
private int bid;
private Set<Person> persons = new HashSet<Person>();
@OneToMany(cascade = {CascadeType.ALL})
@JoinTable(name="person_book",
joinColumns={@JoinColumn(name="bid")},
inverseJoinColumns={@JoinColumn(name="pid")})
public Set<Person> getPersons() {
return persons;
}
public void setPersons(Set<Person> persons) {
this.persons = persons;
}
//Setter & Getter for bid
...
}
在休眠配置中,我有:
<hibernate-configuration>
<session-factory>
...
<mapping class="com.my.db.model.Person" />
<mapping class="com.my.db.model.Book" />
</session-factory>
</hibernate-configuration>
当我开始我的tomecat时,我经常得到以下Hibernate异常:
org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.my.db.model.Person.book references an unknown entity: com.my.db.model.Book
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:109)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1557)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1478)
它抱怨书是一个未知的实体。为什么?我哪里做错了?我觉得问题很可能是关于hibernate注释。。。
(请不要建议我不要使用联接表。谢谢。)
如果你仔细观察你的堆栈,你会看到
Error :org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.my.db.model.Person.book references an unknown entity: com.my.db.model.Book
所以这个领域
@ManyToOne(cascade = {CascadeType.ALL})
@JoinTable(name="person_book",
joinColumns={@JoinColumn(name="pid")},
inverseJoinColumns={@JoinColumn(name="bid")})
public Book getBook() {
return book;
}
是造成问题的原因。@ManyToOne
有一个参数targetEntity
,它说:
(Optional) The entity class that is the target of the association. Defaults to the type of the field or property that stores the association.
从而将您的表结构更新为
表格结构
CREATE TABLE `person` (
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) CHARACTER SET latin1 NOT NULL,
KEY `fk_book_id`
CONSTRAINT `fk_book_id` FOREIGN KEY (`fk_book_id`) REFERENCES `book` (`id`)
PRIMARY KEY (`id`)
) ENGINE=INNODB
CREATE TABLE `book` (
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=INNODB
实体冲突
@Entity
@Table(name = "person")
public class Person {
private int pid;
private Book book;
@ManyToOne()
@JoinColumn(name = "fk_book_id", nullable = false)
public Book getBook() {
return book;
}
//Setter & Getter for pid
...
}
@Entity
@Table(name = "book")
public class Book {
private int bid;
private Set<Person> persons = new HashSet<Person>();
@OneToMany(mappedBy = "book")
public Set<Person> getPersons() {
return persons;
}
//Setter & Getter for bid
...
}
希望这将解决您的问题