【问题标题】:Spring or Hibernate not generating id when username is annotated with @email当用户名使用@email 注释时,Spring 或 Hibernate 不生成 id
【发布时间】:2016-10-09 21:28:32
【问题描述】:

我目前有一个完整的 Spring 应用程序,经过非常彻底的测试,并且已经在生产环境中成功运行了一年多。最近,我想在用户名字段上进行休眠电子邮件验证。用户名字段用于登录,也是我们用户的电子邮件。

当我用@Email 注释username 字段时,不再生成id(用@Id@Generated(strategy = GenerationType.AUTO) 注释)并保留值null。这会导致hashCodeNullPointerException 上失败(不过这没有问题)。所以由于某种原因,由于在User.java 实体中添加了@Email 注释,因此不再生成 id。

@Entity
@Table(uniqueConstraints = @UniqueConstraint(name = "username",
columnNames = "username"))
public class User implements Serializable, UserDetails {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    @Column(nullable = false)
    @JsonView(View.NoProfile.class)
    @Email
    protected String username;

    @Column(nullable = false)
    private String passwordHash;

    @JsonIgnore
    @ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
    @Enumerated(EnumType.STRING)
    @CollectionTable(name = "user_role")
    private Set<Role> roles;

    @OneToOne(targetEntity = Profile.class, cascade = CascadeType.ALL)
    @JsonView(View.Public.class)
    protected Profile profile;

    @JsonIgnore
    private boolean accountNonExpired = true;
    @JsonIgnore
    private boolean accountNonLocked = true;
    @JsonIgnore
    private boolean credentialsNonExpired = true;
    @JsonIgnore
    private boolean enabled = true;

    public User(String username, String passwordHash) {
        this.username = username;
        this.passwordHash = passwordHash;
        this.profile = new Profile();
        this.roles = new HashSet<>();
        roles.add(Role.ROLE_USER);
    }

    User() { // jpa only
    }

    public Profile getProfile() {
        return profile;
    }

    public Long getId() {
        return id;
    }

    public void setPasswordHash(String passwordHash) {
        this.passwordHash = passwordHash;
    }

    @Override
    public Set<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    @Override
    @JsonIgnore
    public String getPassword() {
    return passwordHash;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public void resetProfile() {
        this.profile = new Profile();
    }

    public void addRole(Role role) {
        this.roles.add(role);
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @JsonView(View.Public.class)
    public int getReference() {
        return username.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        User user = (User) o;

        return username.equals(user.username) && id.equals(user.id);

    }

    @Override
    public int hashCode() {
        int result = username.hashCode();
        result = 31 * result + id.hashCode();
        return result;
    }
}

【问题讨论】:

  • 您最近没有更改您的数据库架构/实体吗?然后更新失败?
  • 你有吗? update,或者create也不错。
  • 这发生在createcreate-drop 上,所以数据库应该是正确的。
  • 为什么只有一个字段的类级别的 UniqueConstraint?你不应该把它放在电子邮件上,否则会令人困惑,请参阅stackoverflow.com/questions/15372654/…
  • 这是一种样式选择,我们希望在文件顶部有唯一约束,以使唯一字段立即清晰。此外,不幸的是,这并不能解决手头的问题。不过感谢您的帮助。

标签: java spring hibernate email hibernate-validator


【解决方案1】:

问题可能是当尝试保存用户时,休眠检查它是否有效。如果用户名电子邮件格式有问题,hibernate 不会尝试保存它,因此 id 不会生成 id。

但是验证错误会发生什么?我认为它可能被您在 hashCode 方法中谈论的 NPE 掩盖了。 尝试重写您的 hashCode 以处理可能的 NPE,并检查休眠约束违规。

【讨论】:

  • 所以我重写了哈希码以便能够处理 NPE。它现在可以工作,但这不是我最初想要的解决方案。因此,我可以得出结论,@email 注释导致哈希码更早生成,而 id 生成更晚。由于没有@email 注释,因此从不需要空检查(id 是在哈希码之前生成的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 2012-06-09
  • 2014-09-20
  • 1970-01-01
相关资源
最近更新 更多