Java 当用户名用@email注释时,Spring或Hibernate不生成id

Java 当用户名用@email注释时,Spring或Hibernate不生成id,java,spring,hibernate,email,hibernate-validator,Java,Spring,Hibernate,Email,Hibernate Validator,我目前有一个完全可以工作的Spring应用程序,经过了非常彻底的测试,现在已经在生产中成功运行了一年多。最近,我想对用户名字段进行hibernate电子邮件验证。用户名字段用于登录,也是我们用户的电子邮件 当我用@Email注释用户名字段时,不再生成id(用@id和@Generated(strategy=GenerationType.AUTO))并保留值null。这会导致hashCode在NullPointerException上失败(但这没有问题)。因此,由于某种原因,由于向User.java

我目前有一个完全可以工作的Spring应用程序,经过了非常彻底的测试,现在已经在生产中成功运行了一年多。最近,我想对用户名字段进行hibernate电子邮件验证。用户名字段用于登录,也是我们用户的电子邮件

当我用
@Email
注释
用户名
字段时,不再生成id(用
@id
@Generated(strategy=GenerationType.AUTO)
)并保留值
null
。这会导致
hashCode
NullPointerException
上失败(但这没有问题)。因此,由于某种原因,由于向
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;
    }
}
@实体
@表(uniqueConstraints=@UniqueConstraint(name=“username”,
columnNames=“username”))
公共类用户实现可序列化的UserDetails{
@GeneratedValue(策略=GenerationType.AUTO)
@身份证
私人长id;
@列(nullable=false)
@JsonView(View.NoProfile.class)
@电子邮件
受保护的字符串用户名;
@列(nullable=false)
私有字符串密码哈希;
@杰索尼奥雷
@ElementCollection(targetClass=Role.class,fetch=FetchType.EAGER)
@枚举(EnumType.STRING)
@CollectionTable(name=“用户角色”)
私人设定角色;
@OneTONE(targetEntity=Profile.class,cascade=CascadeType.ALL)
@JsonView(View.Public.class)
保护轮廓;
@杰索尼奥雷
私有布尔值accountNonExpired=true;
@杰索尼奥雷
私有布尔值accountNonLocked=true;
@杰索尼奥雷
private boolean CredentialsNoneExpired=true;
@杰索尼奥雷
私有布尔启用=真;
公共用户(字符串用户名、字符串密码哈希){
this.username=用户名;
this.passwordHash=passwordHash;
this.profile=新的profile();
this.roles=new HashSet();
roles.add(Role.Role\u用户);
}
User(){//仅限jpa
}
公共配置文件getProfile(){
回报曲线;
}
公共长getId(){
返回id;
}
public void setPasswordHash(字符串passwordHash){
this.passwordHash=passwordHash;
}
@凌驾

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

但是验证错误会发生什么呢?我认为它可能被你在hashCode方法中提到的NPE掩盖了。
尝试重新编写哈希代码,注意可能出现的NPE,并检查是否存在违反hibernate约束的情况。

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

但是验证错误会发生什么呢?我认为它可能被你在hashCode方法中提到的NPE掩盖了。
尝试重写哈希代码,注意可能出现的NPE,并检查是否存在hibernate约束冲突。

您最近没有更改数据库架构/实体,是吗?然后更新失败?是否有?更新,或者创建也很好。这发生在
create
create drop
上,因此数据库应该是正确的t、 为什么在类级别上只有一个字段的UniqueConstraint?你不应该把它写在电子邮件上吗?否则会很混乱,看这是一个样式选择,我们希望在文件顶部有唯一的约束,以便立即清除唯一的字段。而且,很遗憾,这并不能解决当前的问题。谢谢不过,为了帮助您。您最近没有更改数据库架构/实体,是吗?然后更新失败?您有吗?更新或创建也很好。这发生在
create
create drop
上,所以数据库应该是正确的。为什么在类级别只有一个字段的UniqueConstraint?不应该吗“你不能把它写在电子邮件上,否则会让人困惑,这是一个样式选择,我们希望在文件顶部有唯一的约束,以便立即清除唯一的字段。而且,不幸的是,这并不能解决手头的问题。谢谢你的帮助。所以我重写了哈希代码,以便能够处理NPE。它现在可以工作了,但这不是我最初想要的解决方案。因此,从我可以得出的结论是,
@email
注释导致hashcode生成较早,id生成较晚。因为没有
@email
注释,就不需要空检查(id在hashcode之前生成)。因此,我重写了hashcode以处理NPE。它现在可以工作,但不是我最初想要的解决方案。因此,从我可以得出的结论是,
@email
注释导致hashcode生成较早,id生成较晚。因为没有
@email
注释,空检查是nev需要er(id是在哈希代码之前生成的)。