【问题标题】:Hibernate validator always says that collection is emptyHibernate 验证器总是说集合是空的
【发布时间】: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


【解决方案1】:

我遇到过类似的问题,hibernate 中似乎有一个错误。验证 Set 或使用 CascadeType.MERGE 时会出现问题,仅当不使用 hibernate 提供的 @Id 生成策略之一时才会出现此问题。 好像你有同样的问题HHH-10246

【讨论】:

  • 在 Hibernate 5.2.0 版本中修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多