我很难搞清楚这一点。我有两个类Employee和Role:
@Entity
@Table(name = "employees")
public class Employee implements Serializable {
private static final long serialVersionUID = 5468763051360122059L;
@Id
@Column(name = "employee_guid", length = 36)
@NotNull
@Size(min = 36, max = 36)
private String id;
@Column(name = "is_active", nullable = false)
private boolean isActive;
@ManyToMany(mappedBy = "employees", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH,
CascadeType.DETACH })
@NotEmpty
@Valid
private List<Role> roles;
@OneToMany(mappedBy = "employee", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH,
CascadeType.DETACH }, orphanRemoval = true)
@Valid
private List<VacationRequest> vacationRequests;
@OneToMany(mappedBy = "manager", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH,
CascadeType.DETACH }, orphanRemoval = true)
private List<ManagerSubordinate> managers;
protected Employee() {
vacationRequests = new ArrayList<VacationRequest>();
managers = new ArrayList<ManagerSubordinate>();
}
public Employee(UUID id, List<Role> roles) {
this(id, roles, true);
}
public Employee(UUID id, List<Role> roles, boolean isActive) {
this();
if (id == null) {
throw new NullPointerException("id cannot be null");
}
this.id = id.toString();
this.roles = roles;
this.isActive = isActive;
}
public UUID getId() {
return UUID.fromString(id);
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public List<VacationRequest> getVacationRequests() {
return vacationRequests;
}
public void setVacationRequests(List<VacationRequest> vacationRequests) {
this.vacationRequests = vacationRequests;
}
public List<ManagerSubordinate> getManagers() {
return managers;
}
public void setManagers(List<ManagerSubordinate> managers) {
this.managers = managers;
}
}
@Entity
@Table(name = "application_roles", uniqueConstraints = { @UniqueConstraint(name = "UK_ROLE_NAME",
columnNames = "name") })
public class Role implements Serializable {
private static final long serialVersionUID = -6126630712163059772L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, length = 50)
@NotNull
@Size(min = 5, max = 50)
private String name;
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST,
CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH })
@JoinTable(name = "employees_application_roles", joinColumns = { @JoinColumn(name = "employee_guid",
nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false) },
foreignKey = @ForeignKey(name = "FK_EMPLOYEE_ROLE", value = ConstraintMode.CONSTRAINT),
inverseForeignKey = @ForeignKey(name = "FK_ROLE_EMPLOYEE", value = ConstraintMode.CONSTRAINT))
@Valid
private List<Employee> employees;
protected Role() {
employees = new ArrayList<Employee>();
}
public Role(String name) {
this();
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
此外,员工与自己有很多关系:
@Embeddable
public class ManagerSubordinateId implements Serializable {
private static final long serialVersionUID = 2145140927848605356L;
@Column(name = "manager_guid", length = 36)
@NotNull
@Size(min = 36, max = 36)
private String managerId;
@Column(name = "subordinate_guid", length = 36)
@NotNull
@Size(min = 36, max = 36)
private String subordinateId;
protected ManagerSubordinateId() {
}
public ManagerSubordinateId(UUID managerId, UUID subordinateId) {
this();
this.managerId = managerId.toString();
this.subordinateId = subordinateId.toString();
}
public UUID getManagerId() {
return UUID.fromString(managerId);
}
public void setManagerId(UUID managerId) {
this.managerId = managerId.toString();
}
public UUID getSubordinateId() {
return UUID.fromString(subordinateId);
}
public void setSubordinateId(UUID subordinateId) {
this.subordinateId = subordinateId.toString();
}
@Override
public int hashCode() {
return managerId.hashCode() + subordinateId.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(!(obj instanceof ManagerSubordinateId))
return false;
ManagerSubordinateId other = (ManagerSubordinateId) obj;
if(!(other.getManagerId().equals(getManagerId())) ||
!(other.getSubordinateId().equals(getSubordinateId()))) {
return false;
}
return true;
}
}
@Entity
@Table(name = "managers_subordinates", uniqueConstraints = @UniqueConstraint(name = "UK_MANAGER_SUBORDINATE",
columnNames = { "manager_guid", "subordinate_guid", "management_type" }))
public class ManagerSubordinate implements Serializable {
private static final long serialVersionUID = 7676137409755328186L;
@EmbeddedId
@NotNull
@Valid
private ManagerSubordinateId managerSubordinateId;
@MapsId("managerId")
@JoinColumn(name = "manager_guid", nullable = false, insertable = false,
updatable = false, foreignKey = @ForeignKey(name = "FK_EMPLOYEE_MANAGER",
value = ConstraintMode.CONSTRAINT))
@ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH,
CascadeType.DETACH })
@NotNull
@Valid
private Employee manager;
@MapsId("subordinateId")
@JoinColumn(name = "subordinate_guid", nullable = false, insertable = false,
updatable = false, foreignKey = @ForeignKey(name = "FK_EMPLOYEE_SUBORDINATE",
value = ConstraintMode.CONSTRAINT))
@ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH,
CascadeType.DETACH })
@NotNull
@Valid
private Employee subordinate;
@Enumerated(EnumType.ORDINAL)
@Column(name = "management_type", nullable = false)
@NotNull
private ManagementType managementType;
protected ManagerSubordinate() {
}
public ManagerSubordinate(ManagerSubordinateId managerSubordinateId, Employee manager, Employee subordinate,
ManagementType managementType) {
this();
this.managerSubordinateId = managerSubordinateId;
this.manager = manager;
this.subordinate = subordinate;
this.managementType = managementType;
}
public ManagerSubordinateId getManagerSubordinateId() {
return managerSubordinateId;
}
public void setManagerSubordinateId(ManagerSubordinateId managerSubordinateId) {
this.managerSubordinateId = managerSubordinateId;
}
public Employee getManager() {
return manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
public Employee getSubordinate() {
return subordinate;
}
public void setSubordinate(Employee subordinate) {
this.subordinate = subordinate;
}
public ManagementType getManagementType() {
return managementType;
}
public void setManagementType(ManagementType managementType) {
this.managementType = managementType;
}
}
当我尝试像这样保存员工时:
Role employeeRole = new Role("Employee");
Employee employee = new Employee(UUID.randomUUID(), Arrays.asList(employeeRole));
employeeRole.getEmployees().add(employee);
employeeRepository.save(employee);
保存因约束验证错误而失败,该错误表明员工内部的角色字段为空,即使它不是(角色被传递给构造函数)。看起来@NotEmpty注释存在一些问题。谁能告诉我我做错了什么?
答案 0 :(得分:0)
我遇到过类似的问题,hibernate似乎有一个bug。在验证Set或使用CascadeType.MERGE时,问题就出现了。这个问题仅在不使用hibernate提供的@Id生成策略时出现。 好像你有同样的问题HHH-10246