我有一个带有数百个类的Spring Boot-Javafx项目,实际上我经常使用双向OneToMany / ManyToOne关系。这就是为什么我真的不知道我的问题的根本原因而感到困惑的原因,因为从本质上讲,这应该是我其他班级的复制/粘贴练习。我试图在团队和雇员之间添加OneToMany / ManyToOne关系,这样每个团队可以分配多个雇员,每个雇员只能是一个团队的成员,就像这样:
package com.agiletunes.shared.domain.security;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import com.agiletunes.shared.domain.organization.Team;
import javafx.collections.FXCollections;
@Entity
@Access(AccessType.PROPERTY) // JPA reading and writing attributes through their getter and setter methods
public class Employee implements Serializable {
private static final long serialVersionUID = 5647322135074737334L;
public static final double DEFAULT_CAPACITY = 6.5; // Default effective working hours per day per employee
private Long id;
protected String name;
protected String firstname;
protected String account; // references "name" field in Account class
protected String phone;
protected String mobile;
protected String emailAddress;
protected List<Role> roles;
protected boolean isIntern;
protected double capacityPerDay;
protected Team team;
// JPA default constructor
public Employee() {
roles = FXCollections.observableArrayList();
isIntern = true;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
@SuppressWarnings("unused") // used by JPA
private void setId(Long id) {
this.id = id;
}
// getter and setter of other fields deleted for brevity
@ManyToOne
@JoinColumn(name = "fk_team")
public Team getTeam() {
return team;
}
public void setTeam(Team newTeam) {
if(team != newTeam) {
team = newTeam;
team.addMember(this);
}
}
@Override
public String toString() {
return getName() + ", " + getFirstname();
}
@Override // taken from Vlad Mihalcea
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee )) return false;
return id != null && id.equals(((Employee) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
和
package com.agiletunes.shared.domain.organization;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Version;
import com.agiletunes.shared.domain.requirements.UserRequirement;
import com.agiletunes.shared.domain.security.Employee;
import javafx.collections.FXCollections;
@Entity
@Access(AccessType.PROPERTY)
public class Team implements Serializable {
private static final long serialVersionUID = 5479263131702523523L;
private Long id;
private Integer version;
protected String identifier;
protected double capacityPerDay;
protected List<UserRequirement> userRequirements; // the teams backlog
protected List<Employee> members;
// JPA default constructor
public Team() {
userRequirements = FXCollections.observableArrayList();
members = FXCollections.observableArrayList();
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
protected Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
// getter and setter of other fields deleted for brevity
@OneToMany(mappedBy="team")
public List<Employee> getMembers() {
return members;
}
protected void setMembers(List<Employee> newMembers) {
this.members = FXCollections.observableList(newMembers);
}
public void addMember(Employee member) {
if( ! members.contains(member)) {
if(members.add(member)) {
setCapacityPerDay(getCapacityPerDay() + Employee.DEFAULT_CAPACITY);
}
member.setTeam(this);
}
}
public void delMember(Employee member) {
if(members.contains(member)) {
if(members.remove(member)) {
setCapacityPerDay(getCapacityPerDay() - Employee.DEFAULT_CAPACITY);
}
member.setTeam(null);
}
}
@Override
public String toString() {
return identifier;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Team )) return false;
return id != null && id.equals(((Team) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
此代码导致
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'organizationEntityManagerFactory' defined in class path resource [com/agiletunes/security/OrganizationConfig.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.agiletunes.shared.domain.security.Employee.team references an unknown entity: com.agiletunes.shared.domain.organization.Team
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
at com.agiletunes.security.AuthServerApp.init(AuthServerApp.java:73)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:841)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$159(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.agiletunes.shared.domain.security.Employee.team references an unknown entity: com.agiletunes.shared.domain.organization.Team
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:97)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1827)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1771)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1658)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:287)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774)
... 18 common frames omitted
我看不到是什么?谢谢您的帮助和时间
答案 0 :(得分:1)
我会检查您的LocalContainerEntityManagerFactoryBean
是否确实正确配置为扫描软件包com.agiletunes.shared.domain.security
和com.agiletunes.shared.domain.organization
中的实体类。
应该是:
localContainerEntityManagerFactoryBean.setPackagesToScan(
"com.agiletunes.shared.domain.security",
"com.agiletunes.shared.domain.organization");
或:
localContainerEntityManagerFactoryBean.setPackagesToScan(
"com.agiletunes.shared.domain");