如何设计依赖于业务代码的 JPA 实体 setter?
How can I design an JPA entity setter that depends on business code?
我有以下实体:
@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 接口暴露给客户端?请注意,实体 class 无法使用 CDI,因此我无法将 PasswordHash 的实例直接注入其中。
处理此问题的一种方法是不直接从您的服务层公开用户实体,仅在内部将其用于持久性。您通常最终所做的基本上是复制一些实体,并来回复制内容。这些 "copied" 类 有时称为数据传输对象。有像 Dozer 这样的工具可以使这更容易,尽管可以说不是更漂亮。
第二种方法是对抗企业Java,避免这些Anemic Objects。但是迟早,您可能必须进行编程查找,因为正如您所说,实体未启用 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 接口暴露给客户端?请注意,实体 class 无法使用 CDI,因此我无法将 PasswordHash 的实例直接注入其中。
处理此问题的一种方法是不直接从您的服务层公开用户实体,仅在内部将其用于持久性。您通常最终所做的基本上是复制一些实体,并来回复制内容。这些 "copied" 类 有时称为数据传输对象。有像 Dozer 这样的工具可以使这更容易,尽管可以说不是更漂亮。
第二种方法是对抗企业Java,避免这些Anemic Objects。但是迟早,您可能必须进行编程查找,因为正如您所说,实体未启用 CDI。这也不是很好,但至少你得到了一些更面向对象的东西。