DTO和实体在一个对象中?

时间:2015-07-01 15:02:48

标签: spring validation jpa

我目前处于两难境地,而且我一直在阅读有关此事的内容。

我正在使我的DTO成为我的实体。它看起来像这样:

@Entity
@PasswordMatches // custom validator
public class User {

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

    @Column
    @NotNullOrEmpty // custom validator
    private String password;

    @Transient
    @NotNullOrEmpty // custom validator
    private String confirmPassword;

Q1 :这是可接受的还是有更好的方法吗?因为目前,在保存User之前,由于显而易见的原因,我正在哈希密码,但如果直接em.persist(user),则由于@PasswordMatches失败而失败。只有在user.setConfirmPassword(hashedPassword)满足验证时才会保存。我在这里做对了吗?

3 个答案:

答案 0 :(得分:11)

虽然EJB3允许将实体用作DTO,但事实是,拥有单独的DTO仍然更好。

您很快就会发现您的实体需要与特定JPA提供程序(如Hibernate)相关的注释,这些注释会将您的实体绑定到持久层。这意味着如果您的实体被“传递”到您的表示层,那么该层需要“了解”您在持久层中使用的特定库/框架。如果你正在做网络的东西,这不是什么大问题,但如果你做富客户(例如Swing)那么这可能是你的客户需要携带的额外包袱。

同样,您需要开始为表示层注释您的实体(例如,使用@Json注释)。将它们放在您的实体中将再次将您的持久层与您的表示层绑定。

最初我们陷入了使用我们的实体将数据传递给我们的富客户端的陷阱,但是当我们意识到我们需要将它们分成DTO和持久性实体时,我们创建了300多个实体类。对于这么多实体来说,这是一次痛苦的经历,但是现在(有超过400个实体课程)我们很高兴我们做到了。

因此,虽然 可以接受您正在做的事情,但您已经遇到了将业务逻辑与持久层混合导致问题的问题。我建议你将这些内容分成DTO和实体,以便将来继续存在问题。

答案 1 :(得分:6)

从短期来看,它似乎很有效率,可以帮助您更快地完成任务。

从长远来看,将DTO和实体分开总是更好。

随着实体之间关系的增长,您将意识到获取一个实体也会导致获取子实体,即使您在特定用例中可能不需要它们。 DTO可帮助您以您需要的方式优化数据库查询,从而使基础实体不受业务用例的影响。

答案 2 :(得分:5)

答案还取决于您的使用案例。考虑这些因素

  1. 如果您预计,将来会将您的服务层公开给各个客户。在这种情况下,将您的实体设计作为服务方法签名的一部分共享,不是一个好主意,这也可能在可扩展设计中造成问题。
  2. 如果您正在开发一个小型/中级应用程序,将性能作为首要考虑因素,您可以只使用服务层(甚至是表示层)中的实体到持久层。实体可以在xml中定义持久性特定配置,而不是通过注释。如果您在DTO和实体之间进行一对一映射,这不是一个糟糕的设计。当然,在这种情况下,您将获得更快的开发和更少的错误。
  3. 如果您打算为表示层(表单bean)保留单独的bean,您还可以考虑混合。例如,对于主实体管理模块 - 使用实体和无DTO。对于交易权利管理模块 - 使用实体和DTO。