如何设计依赖于业务代码的JPA实体setter?

时间:2016-01-28 14:18:19

标签: jpa java-ee ejb cdi

我有以下实体:

@Entity
public class User {

    @Id
    private Integer id;

    private String username;
    private String password;

}

要设置密码,必须提供明文密码,但存储的实际密码是纯文本密码的哈希值。问题是实际的哈希计算是依赖于业务的。更具体地说,我有以下接口和会话Bean:

public interface PasswordHash {
    String hash(String password);
}

@Stateless
public class UserManager {

    @Inject
    private PasswordHash phash;

    public void changeUserPassword(User user, String newPassword) {
        String passwordHash = phash.hash(newPassword);
        /*Set password of 'user'*/
    }
}

有没有办法为User实体的'password'字段设计一个setter,以便UserManager可以更改其值,但没有其他人可以做到这一点?如果不可能,有没有其他方法可以安全地设置密码,而不会将PasswordHash接口暴露给客户端?请注意,CDI不可用于Entity类,因此我无法直接将PasswordHash实例注入其中。

1 个答案:

答案 0 :(得分:1)

解决这个问题的一种方法是不直接从服务层公开User实体,只在内部使用它来实现持久性。你通常最终做的是基本上复制一些实体,并来回复制东西。这些"复制"类有时称为数据传输对象。有一些像Dozer这样的工具可以让这更容易,虽然可以说并不漂亮。

第二种方法是对抗Enterprise Java,并避免这些Anemic Objects。迟早,您可能必须进行编程查找,因为正如您所说,实体不支持CDI。这也不是很好,但至少你会得到一些更面向对象的东西。