【发布时间】:2014-04-08 13:29:12
【问题描述】:
我很难弄清楚这一点。我有两个类 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;
}
}
此外,Employee 与自身有多对多的关系:
@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 注释似乎存在一些问题。谁能告诉我我做错了什么?
【问题讨论】:
-
不确定,可能你已经尝试过了,如果没有尝试.. 在
employeeRepository.save(employee);上放置一个调试点,看看员工是否有角色列表。此外,静态创建一个employee对象,如 Employee emp = new Employee();并设置其字段并尝试将其直接保存在您现在尝试保存的位置 -
已经尝试过了,我得到了相同的结果。我已将默认构造函数设为保护,以确保用户必须向构造函数提供一些值。
-
好的,我一遍又一遍地阅读它找不到问题,也许我应该自己尝试使用嵌入式数据库
-
好的。我将为 ManagerSubordinateId 类添加实现。
-
我觉得员工和角色之间的映射有问题。会更新
标签: java hibernate jpa annotations