【发布时间】:2022-01-04 23:14:32
【问题描述】:
我需要一种标准方法来将 JPA 实体与其 DTO 进行比较,并确定它们是否代表相同的业务对象。我可以想到三种方法,每个 DTO 上的自定义方法,带有静态方法或比较器的接口。
基于 João Dias 的答案,方法 4 - 继承。
优点/缺点
- 方法 1 - 一直都很糟糕
- 方法 2 - 使用接口来支持组合而不是继承,但需要使用自定义方法名称的语义 (
businessKeysMatch()) - 方法 3 - 不需要修改源代码
- 方法 4 - 简化语义,因为它使用标准
equals(),但需要“样板文件equals()/hashcode()
这些方法的任何其他优点/缺点或对其他方法的建议?
最后,我选择了使用方法 2(接口)。继承方法显示出了希望,但是作为 JPA 实体的类之一使映射比我想要的更复杂。
感谢您阅读和思考我的问题!
背景
实体
-
一个数据库键
-
在 ORM 和确定相等性的数据库中唯一强制执行的业务密钥 (
equals()/hashcode()) -
公共属性(姓名、地址、年龄等)
-
非公开/机密属性(密码、刷新令牌、SSN 等)
@Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Entity @Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "businessKey1", "businessKey2" }) }) class UserEntity { @Id Long id; @NotNull @EqualsAndHashCode.Include Long businessKey1; @NotNull @EqualsAndHashCode.Include Long businessKey2; String name; Integer age; String password; String refreshToken; String SSN; }
DTO(完整)
-
确定相等性的业务密钥 (
equals()/hashcode()) -
公共属性(姓名、地址、年龄等)
@Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) class UserDto { @EqualsAndHashCode.Include @NotNull Long businessKey1; @EqualsAndHashCode.Include @NotNull Long businessKey2; String name; String address; Integer age; }
DTO(有限)
-
确定相等性的业务密钥 (
equals()/hashcode()) -
选定的公共属性(名称)
@Data @EqualsAndHashCode(onlyExplicitlyIncluded = true) class UserNameDto { @EqualsAndHashCode.Include @NotNull Long businessKey1; @EqualsAndHashCode.Include @NotNull Long businessKey2; String name; }
方法 1 - 添加到每个 User*Dto 的自定义方法
boolean businessKeysMatch(UserEntity entity) {
if((this.getBusinessKey1() == entity.getBusinessKey1()) && (this.getBusinessKey2() == entity.getBusinessKey2()))
return true;
return false;
}
方法二 - 将静态方法添加到通用接口
interface UserKeys {
Long getBusinessKey1();
Long getBusinessKey2();
static boolean businessKeysMatch(UserKeys o1, UserKeys o2) {
if((o1.getBusinessKey1() == o2.getBusinessKey1()) && (o1.getBusinessKey2() == o2.getBusinessKey2()))
return true;
return false;
}
}
class UserEntity implements UserKeys {
// no other changes
}
class UserDto implements UserKeys {
// no other changes
}
class UserEntity implements UserKeys {
// no other changes
}
方法 3 - 比较器
interface UserBusinessKey {
Long getBusinessKey1();
Long getBusinessKey2();
}
class UserDto implements UserCompare {
// no other changes
}
class UserEntity implements UserCompare {
// no other changes
}
class UserCompare implements Comparator<UserBusinessKey> {
public int compare(UserBusinessKey o1, UserBusinessKey o2) {
int key1Compare = o1.getBusinessKey1().compareTo(o2.getBusinessKey1());
if (key1Compare == 0)
return o1.getBusinessKey2().compareTo(o2.getBusinessKey2());
return key1Compare;
}
}
方法 4 - 仅使用基类的 equals/hashcode 进行继承
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Data
abstract class UserBase {
@NotNull
Long businessKey1;
@NotNull
Long businessKey2;
// lombok generates a standard equals() / hashcode() pair
}
@SuperBuilder
@Getter
@Setter
@ToString
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "businessKey1", "businessKey2" }) })
class UserEntity extends UserBase {
@Id
Long id;
String name;
Integer age;
String password;
String refreshToken;
String SSN;
// handcoded equals/hashcode that only call super
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
@SuperBuilder
@Getter
@Setter
@ToString
class UserDto extends UserBase {
String name;
String address;
Integer age;
// handcoded equals/hashcode that only call super
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
【问题讨论】:
标签: java jpa spring-data-jpa lombok