代码之家  ›  专栏  ›  技术社区  ›  Tim

Spring boot hibernate-针对未映射类使用@onetomany

  •  0
  • Tim  · 技术社区  · 7 年前

    认识到这方面已经有很多问题了,我无法从我的具体案例中看出问题所在。我的应用程序中还有另一个这样的实例(它工作正常),据我所知,我正在镜像配置。实际上,当我使用 mvn: spring-boot:run 一切正常,所有数据按预期找到。但是,当我尝试为应用程序运行测试时,任何使用

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

    产生此错误:

    java.lang.illegalStateException:未能加载ApplicationContext 原因:org.springframework.beans.factory.bean CreationException: 在类中创建名为“EntityManagerFactory”的bean时出错 路径资源 [org/springframework/boot/autoconfigure/orm/jpa/hibernatejpacconfiguration.class]: 调用init方法失败;嵌套异常为 org.hibernate.annotationexception:使用@onetomany或@manytomany 针对未映射类: com.utilities.domain.manufacturing.machine.operators[com.humanresources.domain.machineoperator] 由:org.hibernate.annotationException:使用@onetomany或 @针对未映射类的许多类: 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());
        }
    }
    

    机器操作员ID

    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;
        }
    }
    

    任何人都知道什么是错误的,或者有更好的方法得到同样的结果吗?(我希望能够查看员工并查看他们可以操作的机器,或者查看机器并查看所有可以操作的员工。)我使用的是SpringBoot2.0.3。谢谢!

    3 回复  |  直到 7 年前
        1
  •  2
  •   Karthik R    7 年前

    通常,如果您的 javax.persistence @Entity 没有注释,或者实体是否扫描。如果在注释中尝试了给定的选项,请按以下步骤进行调试:

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

    查找以下或类似日志:
    o.hibernate.jpa.internal.util.LogHelper : PersistenceUnitInfo . . . Managed classes names [ . . ]

    这样,您就可以了解已注册的实体。检查是否从路径扫描实体。

    • 其次,如果您的实体已加载,请更改 IdClass 机器操作员ID 只有特定的列字段而不是对象。从Hibernate规范中,我引用:

    将多个属性映射为@id属性并声明一个外部 类作为标识符类型。这门课,应该是 可序列化,通过@idclass注释在实体上声明。 标识符类型必须包含与标识符相同的属性 实体的属性:每个属性名必须相同,其 如果实体属性是基本的,则类型也必须相同 类型, 其类型必须是关联的 实体(如果实体属性是关联) (一对一或 一个@manytoone)。

    • 如果这是可更改的代码,请简化您的关联。使用 @Id 对于单独的列,也可以使用 @ManyToOne 不同字段上的关联。当然,你的关系可以简化很多。
        2
  •  0
  •   Hakuna Matata    7 年前

    从MachineOperator类中移除Employee和Machine对象,并将其替换为其中的MachineOperatorID实例。在machineOperatorID类中创建machine id和operator id,并用@id注释实例,这样可以解决您的问题,这是在hibernate中执行操作的正确方式。

        3
  •  0
  •   Mohamed Makkaoui    7 年前

    首先,您需要通过将ID更改为基元类型来编辑MachineOperatorID类,例如:

    public class MachineOperatorID implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private int employee;
    private int machine; 
    
    ...
    }
    

    看看能不能解决问题。或者您可以考虑从docs中获得这种方法:

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