Spring Boot休眠-使用@OneToMany定位未映射的类

时间:2018-06-22 20:14:04

标签: hibernate spring-boot spring-data-jpa

认识到已经对此有很多疑问,我看不到我的具体情况的问题。我在我的应用程序中有另一个实例(运行良好),据我所知我正在镜像配置。实际上,当我使用mvn: spring-boot:run运行应用程序时,一切正常,并且所有数据均按预期方式找到。但是,当我尝试为应用程序运行测试时,使用该测试的任何测试

@RunWith(SpringRunner.class)
@DataJpaTest
public class TestClass {
    @Autowired
    private TestEntityManager em;
    ...
}

产生此错误:

  

java.lang.IllegalStateException:无法加载ApplicationContext   引起原因:org.springframework.beans.factory.BeanCreationException:   创建类中定义的名称为'entityManagerFactory'的bean时出错   路径资源   [org / springframework / boot / autoconfigure / orm / jpa / HibernateJpaConfiguration.class]:   调用init方法失败;嵌套异常为   org.hibernate.AnnotationException:使用@OneToMany或@ManyToMany   定位未映射的类:   com.utilities.domain.manufacturing.Machine.operators [com.humanresources.domain.MachineOperator]   原因:org.hibernate.AnnotationException:使用@OneToMany或   @ManyToMany定位未映射的类:   com.utilities.domain.manufacturing.Machine.operators [com.humanresources.domain.MachineOperator]

诚然,我对配置没有很好的了解,但是我对为什么一组类起作用却没有意义。这是类(仅包含相关部分):

员工

@Entity
@Table(name="humanresources.employees")
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;

    private int employeeID;
    ...
    private List<MachineOperator> machines = new ArrayList<>();

    public Employee() {}

    @Id
    @Column(name="pk_employeeid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonView(View.SimpleEmployeeView.class)
    public int getEmployeeID() {
        return employeeID;
    }

    public void setEmployeeID(int employeeID) {
        this.employeeID = employeeID;
    }

    ...    
    @OneToMany(mappedBy="employee",cascade=CascadeType.ALL,orphanRemoval=true)
    @JsonView(View.EmployeeView.class)
    public List<MachineOperator> getMachines() {
        return machines;
    }

    public void setMachines(List<MachineOperator> machines) {
        this.machines = machines;
    }

    public void addMachine(Machine machine) {
        MachineOperator machineOperator = new MachineOperator(this, machine);
        this.machines.add(machineOperator);
        machine.getOperators().add(machineOperator);
    }

    public void removeCompany(Machine machine) {
        for (Iterator<MachineOperator> iterator = machines.iterator(); iterator.hasNext(); ) {
            MachineOperator machineOperator = iterator.next();

            if (machineOperator.getEmployee().equals(this) &&
                    machineOperator.getMachine().equals(machine)) {
                iterator.remove();
                machineOperator.getMachine().getOperators().remove(machineOperator);
                machineOperator.setEmployee(null);
                machineOperator.setMachine(null);
            }
        }
    }
}

机器

@Entity
@Table(name="utilities.mnfg_machines")
public class Machine implements Serializable {
    private static final long serialVersionUID = 1L;

    private int machineID;
    ...
    private List<MachineOperator> operators = new ArrayList<>();

    public Machine() {}

    @Id
    @Column(name="pk_machineid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonView({View.MachineView.class,View.DefaultMachineView.class})
    public int getMachineID() {
        return machineID;
    }

    public void setMachineID(int machineID) {
        this.machineID = machineID;
    }

    ...

    @OneToMany(mappedBy="machine",orphanRemoval=true)
    @JsonView({View.MachineView.class,View.DefaultMachineView.class})
    public List<MachineOperator> getOperators() {
        return operators;
    }

    public void setOperators(List<MachineOperator> operators) {
        this.operators = operators;
    }
}

机器操作员

@Entity
@Table(name="humanresources.employee_machineoperators")
@IdClass(MachineOperatorID.class)
public class MachineOperator implements Serializable {
    private static final long serialVersionUID = 1L;

    private Employee employee;
    private Machine machine;
    private SkillLevel skillLevel;

    public MachineOperator() {}

    public MachineOperator(Employee employee, Machine machine) {
        this.employee = employee;
        this.machine = machine;
    }

    public MachineOperator(Employee employee, Machine machine, SkillLevel skillLevel) {
        this.employee = employee;
        this.machine = machine;
        this.skillLevel = skillLevel;
    }

    @Id
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="fk_employeeid")
    @JsonView(View.SimpleEmployeeView.class)
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    @Id
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="fk_machineid")
    public Machine getMachine() {
        return machine;
    }

    public void setMachine(Machine machine) {
        this.machine = machine;
    }

    @ManyToOne
    @JoinColumn(name="fk_skilllevelid")
    public SkillLevel getSkillLevel() {
        return skillLevel;
    }

    public void setSkillLevel(SkillLevel skillLevel) {
        this.skillLevel = skillLevel;
    }

    @Override
    public int hashCode() {
        return Objects.hash(machine, employee);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;

        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        MachineOperator other = (MachineOperator) obj;
        return Objects.equals(machine, other.getMachine()) && Objects.equals(employee, other.getEmployee());
    }
}

MachineOperatorID

public class MachineOperatorID implements Serializable {
    private static final long serialVersionUID = 1L;

    private Employee employee;
    private Machine machine;

    public MachineOperatorID() {}

    public MachineOperatorID(Employee employee, Machine machine) {
        this.employee = employee;
        this.machine = machine;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public Machine getMachine() {
        return machine;
    }

    public void setMachine(Machine machine) {
        this.machine = machine;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + Objects.hashCode(this.machine);
        hash = 83 * hash + Objects.hashCode(this.employee);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MachineOperatorID other = (MachineOperatorID) obj;
        if (!Objects.equals(this.machine, other.machine)) {
            return false;
        }
        if (!Objects.equals(this.employee, other.employee)) {
            return false;
        }
        return true;
    }
}

任何人都知道什么地方出了问题,还是有更好的方法来获得相同的结果? (我希望能够查看一个雇员并查看他们可以操作的机器,或者查看一个计算机并查看所有可以操作该机器的雇员。)我正在使用Spring Boot 2.0.3。谢谢!

3 个答案:

答案 0 :(得分:2)

通常,如果未注释javax.persistence的{​​{1}}或未扫描实体,就会发生这种情况。如果您已尝试使用注释中的给定选项,请按以下步骤进行调试:

  • 在application.yaml / properties或log4j2.xml或任何日志记录配置中启用 @Entity org.hibernate日志记录。

寻找以下或类似的日志:
DEBUG

到此,您将知道注册实体。检查是否从路径中扫描了您的实体。

  • 第二,如果您的实体已加载,请更改您的o.hibernate.jpa.internal.util.LogHelper : PersistenceUnitInfo . . . Managed classes names [ . . ] MachineOperatorID ,使其仅具有特定的列字段而没有对象。从休眠规范中,我引用:
  

将多个属性映射为@Id属性并声明一个外部   class为标识符类型。这个课,需要   可序列化,通过@IdClass注释在实体上声明。   标识符类型必须包含与标识符相同的属性   实体的属性:每个属性名称必须相同,其属性   如果实体属性属于基本类型,则类型也必须相同   类型,其类型必须是关联的主键的类型   实体,如果实体属性是关联(@ OneToOne或   @ManyToOne)。

  • 如果这是可更改的代码,请简化关联。对各个列使用IdClass,并且在不同字段上分别使用@Id关联。绝对可以简化您的关系。

答案 1 :(得分:0)

从machineoperator类中删除雇员和机器对象,并将其替换为其中的MachineOperatorID实例。并在MachineOperatorID类中创建计算机ID和操作员ID,并使用@ID注释实例,这将解决您的问题,这就是在休眠状态下做事的正确方法。

答案 2 :(得分:0)

首先,您需要通过将ID更改为原始类型来编辑MachineOperatorID类:

public class MachineOperatorID implements Serializable {
private static final long serialVersionUID = 1L;

private int employee;
private int machine; 

...
}

,看看是否可以解决问题。或者,也许您应该考虑从文档中使用这种方法:

  

如果您希望加载完整的应用程序配置,但是   使用嵌入式数据库,应考虑将@SpringBootTest组合使用   使用@AutoConfigureTestDatabase而不是此注释。