【问题标题】:Spring Framework + Spring Data + Hibernate Jpa OneToMany child removal failsSpring Framework + Spring Data + Hibernate Jpa OneToMany 子删除失败
【发布时间】:2016-03-04 08:48:48
【问题描述】:

我的(Spring Framework + Spring Data + Hibernate JPA)项目中有一个单向 OneToMany JPA 实体映射。实体类如以下代码所示。(为简洁起见,我删除了不相关的类成员)。

@Entity
@Table(name = "employees")
class Employee{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Integer id;

   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "employee_id")
   private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}

@Entity
@Table(name = "department_assignments")
class DepartmentAssignment{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Integer id;

   @NotNull
   @Column(name = "employee_id")
   private Integer employeeId;

   @NotNull
   @Column(name = "department_id")
   private Integer departmentId;
}

@Entity
@Table(name = "departments")
class Department{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Integer id;       
}

而且,在我的一个服务类中,有一种方法可以从 Employee 中删除 DepartmentAssignment,如下所示。

public Employee deleteDepartmentAssignment(Integer empId, Integer deptAssignmentId) {
        Employee employee = employeeRepository.findOne(empId);
        if(employee != null) {
            for ( DepartmentAssignment da : employee.getDepartmentAssignments()) {
                if(da.getId().equals(deptAssignmentId)) {
                    employee.getDepartmentAssignments().remove(da);
                    employee = employeeRepository.save(employee);
                    break;
                }
            }
        }

        return employee;
    }

但是,调用上述方法给我一个错误:org.hibernate.exception.ConstraintViolationException,并且在 SQL 日志中,我可以看到事务的最后一条 SQL 语句的Column 'employee_id' cannot be null 错误。

谁能告诉我我在这里做错了什么以及如何解决它?

【问题讨论】:

  • 请添加完整的堆栈跟踪。
  • DepartmentAssignment 类中还有其他内容吗?如果不是,那有什么意义。您可以删除它而不会造成任何功能损失。

标签: spring hibernate jpa spring-data


【解决方案1】:

你不需要添加

@NotNull
@Column(name = "employee_id")
private Integer employeeId;

Employee,如果你使用@JoinColumn(name = "employee_id")。尝试删除它。

【讨论】:

  • 尝试你的建议会给我以下错误,它也无法加载弹簧上下文。 ` org.hibernate.DuplicateMappingException: 表 [departments_assignments] 包含由不同逻辑列名称表示的物理列名称 [employee_id]:[employeeId]、[employee_id] `
  • @Tharanga 您应该从DepartmentAssignment 中删除所有employeeIdemployee_id 并更新架构。
  • 我要谢谢你。完全删除 employeeId 就像一个魅力。
  • @Tharanga 欢迎您。感谢您的投票。 private Integer departmentId; 看起来也很奇怪。请永远不要使用这样的关联。您应该使用与对象的关联(例如使用惰性)。
【解决方案2】:

您可以尝试以下方法,不确定为什么在对象中使用普通 id。那不是对象关系映射。 更多详情见Hibernate triggering constraint violations using orphanRemoval

@Entity
@Table(name = "employees")
class Employee{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", orphanRemoval = true)
   private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}

@Entity
@Table(name = "department_assignments")
class DepartmentAssignment{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

   @ManyToOne(optional=false)
   private Employee employee;

   @ManyToOne(optional=false)
   private Department department;
}

@Entity
@Table(name = "departments")
class Department{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;       
}

【讨论】:

  • 感谢您前来帮助我。我没有让它双向的原因是,根据我的业务模型,它不打算从 DepartmentAssignment 访问 Employee。你的建议让它双向应该有效。我从 DepartmentAssignment 实体中完全删除了employeeId,它现在按预期工作。
【解决方案3】:

你必须查看 .hbm.xml 文件并且你应该在这个文件中映射你的实体并且 你可以看看这个例子

http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example/

希望对你有用。

【讨论】:

  • 没用。因为他使用的是注解映射,而不是 xm-mapping。
  • 我没有使用 .hbm 文件。它的所有基于注解的映射与 hibernate-jpa。
【解决方案4】:

尝试删除

cascade = CascadeType.ALL

但我不是 100% 确定..

【讨论】:

  • 你试过了吗? ,我就是这个原因
  • 不可能通过默认cascading的父级更新子级。
  • 然后添加相关的级联类型而不是All。像 CascadeType.Merge
  • 有可能。但是,我认为,问题的原因不是cascade
  • 嗯好的,但是 CascadeType.All 意味着对父对象的任何更改都会标记子对象以进行更新
猜你喜欢
  • 1970-01-01
  • 2014-11-16
  • 1970-01-01
  • 2015-06-28
  • 2019-05-17
  • 1970-01-01
  • 2014-05-28
  • 1970-01-01
  • 2012-05-21
相关资源
最近更新 更多