Hibernate验证器总是说集合是空的

时间:2014-04-08 13:29:13

标签: java hibernate jpa annotations

我很难搞清楚这一点。我有两个类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注释存在一些问题。谁能告诉我我做错了什么?

1 个答案:

答案 0 :(得分:0)

我遇到过类似的问题,hibernate似乎有一个bug。在验证Set或使用CascadeType.MERGE时,问题就出现了。这个问题仅在不使用hibernate提供的@Id生成策略时出现。 好像你有同样的问题HHH-10246