我遇到了映射我的实体以使用@Embeddable类作为连接类代表来实现多对多连接表的问题。基本上这就是我想要实现的目标:
我按照Java Hibernate Persistence一书中给出的教程,我仍然收到这些方法的错误:
org.hibernate.AnnotationException:使用@OneToMany或@ManyToMany定位未映射的类:nz.co.doltech.ims.project.server.entities.CategoryEntity.incidentCategoryJoins [nz.co.doltech.ims.project.server .entities.IncidentCategoryJoin] 在org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1185) 在org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:710) 在org.hibernate.cfg.annotations.CollectionBinder $ 1.secondPass(CollectionBinder.java:645) 在org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:65) 在org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1716) 在org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1423) 在org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375) 在org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:720) 在org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:188) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1541) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
我正在使用spring设置休眠:
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
Spring Appcontext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<context:annotation-config />
<context:component-scan base-package="nz.co.doltech.ims" />
<aop:aspectj-autoproxy />
<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:nz/co/doltech/ims/paths.properties</value>
<value>classpath:nz/co/doltech/ims/project/project.properties</value>
<value>classpath:nz/co/doltech/ims/framework/framework.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="no"/>
</bean>
<!-- Hibernate Data Source -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${project.database.driver}" />
<property name="url" value="${project.database.url}" />
<property name="username" value="${project.database.user}" />
<property name="password" value="${project.database.password}" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><!-- depends-on="flyway" -->
<!-- property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /-->
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="packagesToScan">
<list>
<value>${paths.project}.server.entities</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${project.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${project.hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${project.hibernate.hbm2ddl}</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
以下是我带注释的实体类
CategoryEntity.java:
@javax.persistence.Entity
@Table(name = "categories")
public class CategoryEntity implements Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private int id = Entity.UNSAVED_ID;
@Basic(optional = false)
@Column(nullable = false, length = 128)
private String name;
@Basic(optional = false)
@Column(nullable = false, length = 512)
private String description;
@OneToMany(mappedBy = "category")
private Set<IncidentCategoryJoin> incidentCategoryJoins;
@JoinTable(
name = "category_categorytype",
joinColumns = @JoinColumn(name = "category_id")
)
private Set<CategoryTypeJoin> categoryTypeJoins;
// id column
@Override
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
// name column
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
// description column
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
// incident join columns
public Set<IncidentCategoryJoin> getIncidentCategoryJoins() {
return incidentCategoryJoins;
}
public void setIncidentCategoryJoins(Set<IncidentCategoryJoin>
incidentCategoryJoins) {
this.incidentCategoryJoins = incidentCategoryJoins;
}
// category type join columns
public Set<CategoryTypeJoin> getCategoryTypeJoins() {
return categoryTypeJoins;
}
public void setCategoryTypeJoins(Set<CategoryTypeJoin> categoryTypeJoins) {
this.categoryTypeJoins = categoryTypeJoins;
}
}
IncidentsEntity.java:
@javax.persistence.Entity(name = "incidents")
public class IncidentEntity implements Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private int id = Entity.UNSAVED_ID;
@Basic
private String owner;
@Column(length = 256)
private String description;
@Column(name="creation_date")
private String creationDate;
@Column(length = 128)
private String title;
@Column(length = 20)
private String date;
@Column(name="location_details", length = 512)
private String locationDetails;
@Column(name="authorities_involved", length = 512)
private String authInvolved;
private int status;
private int state;
@Column(name="sub_state")
private int subState;
@Column(name="reported_by")
private int reportedBy;
@JoinTable(
name = "incident_category",
joinColumns = @JoinColumn(name = "incident_id")
)
@Embedded
private Set<IncidentCategoryJoin> incidentCategoryJoins;
// id column
@Override
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
// description column
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
// owner column
public String getOwner() {
return this.owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
// creation date column
public String getCreationDate() {
return this.creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
// title column
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
// date column
public String getDate() {
return this.date;
}
public void setDate(String date) {
this.date = date;
}
// location details column
public String getLocationDetails() {
return locationDetails;
}
public void setLocationDetails(String locationDetails) {
this.locationDetails = locationDetails;
}
// authorities involved column
public String getAuthInvolved() {
return authInvolved;
}
public void setAuthInvolved(String authInvolved) {
this.authInvolved = authInvolved;
}
// status column
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
// state column
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
// sub state column
public int getSubState() {
return subState;
}
public void setSubState(int subState) {
this.subState = subState;
}
// reported by column
public int getReportedBy() {
return reportedBy;
}
public void setReportedBy(int reportedBy) {
this.reportedBy = reportedBy;
}
// categories join columns
public Set<IncidentCategoryJoin> getIncidentCategoryJoins() {
return incidentCategoryJoins;
}
public void getIncidentCategoryJoins(Set<IncidentCategoryJoin>
incidentCategoryJoins) {
this.incidentCategoryJoins = incidentCategoryJoins;
}
}
CategoryTypeEntity.java:
@javax.persistence.Entity
@Table(name = "categorytypes")
public class CategoryTypeEntity implements Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id = Entity.UNSAVED_ID;
@Basic(optional = false)
@Column(nullable = false, length = 128)
private String name;
@Basic(optional = false)
@Column(nullable = false, length = 512)
private String description;
@OneToMany(mappedBy = "categoryType")
private Set<CategoryTypeJoin> categoryTypeJoins;
@OneToMany(mappedBy = "categoryType")
private Set<IncidentCategoryJoin> incidentCategoryJoins;
@Override
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<CategoryTypeJoin> getCategoryTypeJoins() {
return categoryTypeJoins;
}
public void setCategoryTypeJoins(Set<CategoryTypeJoin>
categoryTypeJoins) {
this.categoryTypeJoins = categoryTypeJoins;
}
}
所以我使用@Embeddable注释加入这些表,以便hibernate可以将它映射到实体中。但正如您在错误消息中看到的那样,它根本就不是映射。
IncidentCategoryJoin.java:
@Embeddable
public class IncidentCategoryJoin implements Serializable {
@Parent // Optional back-pointer
private IncidentEntity incident;
@ManyToOne
@JoinColumn(name="category_id",
insertable = false,
updatable = false)
private CategoryEntity category;
@ManyToOne
@JoinColumn(name="categorytype_id",
insertable = false,
updatable = false)
private CategoryTypeEntity categoryType;
public IncidentCategoryJoin() {}
public IncidentCategoryJoin(
IncidentEntity incident,
CategoryEntity category,
CategoryTypeEntity categoryType) {
// Set fields
this.incident = incident;
this.category = category;
this.categoryType = categoryType;
// Guarantee referential integrity
incident.getIncidentCategoryJoins().add(this);
category.getIncidentCategoryJoins().add(this);
}
public IncidentEntity getIncident() {
return incident;
}
public void setIncident(IncidentEntity incident) {
this.incident = incident;
}
public CategoryEntity getCategory() {
return category;
}
public void setCategory(CategoryEntity category) {
this.category = category;
}
public CategoryTypeEntity getCategoryType() {
return categoryType;
}
public void setCategoryType(CategoryTypeEntity categoryType) {
this.categoryType = categoryType;
}
public boolean equals(Object o) {
if (o != null && o instanceof IncidentCategoryJoin) {
IncidentCategoryJoin that = (IncidentCategoryJoin)o;
return this.category.equals(that.getCategory()) &&
this.incident.equals(that.getIncident()) &&
this.categoryType.equals(that.getCategoryType());
} else {
return false;
}
}
public int hashCode() {
return category.getId() + incident.getId() + categoryType.getId();
}
}
CategoryTypeJoin.java:
@Embeddable
public class CategoryTypeJoin implements Serializable {
@Parent // Optional back-pointer
private CategoryEntity category;
@ManyToOne
@JoinColumn(name="categorytype_id",
insertable = false,
updatable = false)
private CategoryTypeEntity categoryType;
public CategoryTypeJoin() {}
public CategoryTypeJoin(
CategoryEntity category,
CategoryTypeEntity categoryType) {
// Set fields
this.category = category;
this.categoryType = categoryType;
// Guarantee referential integrity
category.getCategoryTypeJoins().add(this);
categoryType.getCategoryTypeJoins().add(this);
}
public CategoryEntity getCategory() {
return category;
}
public void setCategory(CategoryEntity category) {
this.category = category;
}
public CategoryTypeEntity getCategoryType() {
return categoryType;
}
public void setCategoryType(CategoryTypeEntity categoryType) {
this.categoryType = categoryType;
}
public boolean equals(Object o) {
if (o != null && o instanceof IncidentCategoryJoin) {
IncidentCategoryJoin that = (IncidentCategoryJoin)o;
return this.category.equals(that.getCategory()) &&
this.categoryType.equals(that.getCategoryType());
} else {
return false;
}
}
public int hashCode() {
return category.getId() + categoryType.getId();
}
}
有没有人知道为什么这对我不起作用?请记住,我已经从官方Java Hibernate Persistence一书中遵循了这个方法,所以理论上它应该对我来说很好。我一直在考虑在Spring或hibernate中出现bug的可能性。无论如何,我很感激我能得到的任何帮助。
干杯, Ben Dol
答案 0 :(得分:2)
错误,不,这不是映射多对多关联的方式。不应将连接表映射为实体。你应该只有三个实体:
事件&lt; - &gt;类别&lt; - &gt; CategoryType
联接表应仅用于映射多对多关联,在official documentation中有描述。