在尝试使用注释设置我的模式时,我遇到了一些令人沮丧的 Hibernate 行为。假设我有一个与其他几种类型具有一对多关系的实体。例如:
@Entity
@Table(name = "clubs")
public class Club {
private long id;
private String name;
//...
private Collection<ClubLocation> locations;
public Club() {
this.name = null;
//...
this.locations = Collections.emptyList();
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(mappedBy = "club")
public Collection<ClubLocation> getLocations() {
return locations;
}
public void setLocations(Collection<ClubLocation> locations) {
this.locations = locations;
}
}
现在正如我提到的,我想将此实体与许多其他实体相关联,因此定义一个管理关系的超类实体似乎是个好主意,Club
这样我就不需要在每个关联的实体中设置关系班级。我这样做使用:
@Entity
@Table(name = "clubItems")
@Inheritance(strategy = InheritanceType.JOINED)
public class ClubItem {
protected Club club;
public ClubItem() {
this.club = null;
}
@ManyToOne(optional = false)
public Club getClub() {
return club;
}
public void setClub(Club club) {
this.club = club;
}
}
然后我像这样扩展该类:
@Entity
@Table(name = "clubLocations")
public class ClubLocation extends ClubItem {
private String title;
//...
public ClubLocation() {
this.title = null;
//...
}
@Column(nullable = false)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
一切似乎都很好,除了当我尝试运行然后 Hibernate 爆炸时:
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: ClubLocation.club in Club.locations
[WARNING] [talledLocalContainer] at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:543)
[WARNING] [talledLocalContainer] at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:508)
[WARNING] [talledLocalContainer] at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43)
[WARNING] [talledLocalContainer] at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1127)
[WARNING] [talledLocalContainer] at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296)
[WARNING] [talledLocalContainer] at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1112)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1233)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:154)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:869)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:183)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:240)
[WARNING] [talledLocalContainer] at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:120)
[WARNING] [talledLocalContainer] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
[WARNING] [talledLocalContainer] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
令人沮丧的是,如果我复制类club
内部属性的 getter 和 setter 声明ClubLocation
,一切都很好。具体来说,如果我添加它可以找到:
@Override
@ManyToOne(optional = false)
public Club getClub() {
return super.getClub();
}
public void setClub(Club club) {
super.setClub(club);
}
...进入ClubLocation
课堂。但这毫无意义,因为它所做的只是委托给超类。
Hibernate 是否不够复杂,无法在没有在子类中重新声明 getter/setter 的情况下处理继承的映射字段?如果 Hibernate 可以更优雅地处理这种情况,它需要如何设置/我做错了什么?