JPA的模式:从实体生成数据传输对象DTO并将DTO合并到数据库

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA的模式:从实体生成数据传输对象DTO并将DTO合并到数据库相关的知识,希望对你有一定的参考价值。

我正在寻找一种从JPA实体创建数据传输对象(DTO)的好方法,反之亦然。我想将DTO作为JSON发送到客户端,然后接收修改后的DTO并将其保存回数据库。在从JSON解析为Java类之后,从接收到的对象上的EntityManager执行合并方法将是最容易的。

例如,有以下Entity和Rest方法用于保存修改后的对象:


@Entity
@Table(name="CUSTOMER")
public class Customer {
    @Id
    Long id;
    @Version
    Long version;
    String name;
    String address;
    String login;
    String password;
    String creditCardNumber;
    @OneToMany(cascade = CascadeType.ALL)
    List<Foo> fooList;

    ... Getter() and Setter()
}

private EntityManager em;
@POST
@Path("/saveCustomer")
public void saveCustomer ( Customer  customer)   {               
   em.merge(customer);
   return;
}  

只要我将整个实体类作为JSON发送并接收整个实体,这样就可以正常工作。然后,EntityManager将修改后的对象合并到数据库中。但是当我只想提供实体的一个子集(比如只有客户的名称和地址)时,会出现问题:

  1. 创建实体子集的最佳方法是什么? - 手工编写实体的DTO?这将为实体的每个子集生成重复的代码,必须对其进行维护。
  2. 如何将作为实体子集的DTO合并回数据库? - 使用EntityManager的merge()方法不起作用。起初,DTO不是实体,因此无法合并。只需从DTO创建实体,实体中就会有一些未设置的值。合并后,数据库中的值将为NULL。

我想出的一个想法是为我想要为实体指定的每个子集指定其他实体。 (就像数据库视图一样)这将是重复的代码,但它可以解决DTO与数据库合并的问题。 (也许这段代码可以自动生成)

例如,实体CustomerView1链接到与Customer类相同的表,但仅提供客户的名称和地址。它是真正的Customer类的DTO,可以作为JSON发送并在服务器外部进行修改。然后,该类也可以由EntityManager合并到数据库。

@Entity
@Table(name="CUSTOMER")
public class CustomerView1 {
    @Id
    Long id;
    @Version
    Long version;
    String name;
    String address;
    
        ... Getter() and Setter()
}    

但我对这个解决方案有疑问,我不知道这是否会破坏JPA对实体的缓存并可能导致一些问题。


我的问题是,是否有一种模式可以解决DTO的代码重复并将DTO合并回数据库?

或者是否有用于此目的的图书馆? - 某些东西,比如DTO的自动生成和将DTO复制回真实实体,以便可以将它们与EntityManager合并。

答案

如果实体与DTO之间的大小差异不大,您可以选择发送实体。

使用DTO时,要克服lost update等并发问题,必须在DTO中加入实体版本。

如果您不使用实体版本,并且在REST GET和PUT方法之间更改了基础行,您将覆盖最终用户并不真正意识到的更改。

每当我必须改变一个实体(创建,更新,删除)时,我依赖于JPA and Hibernate Optimistic Locking mechanism

对于UI列表,表格,搜索结果DTO是可行的选项,因为您只对原始实体的投影感兴趣。这样可以加快检索速度,并且您可以从JPA不支持的其他SQL功能(窗口函数)中受益。

另一答案

看一下直接解决问题的Value Object设计模式。

本教程对值对象进行了很好的介绍。

http://www.javastuff.in/2012/04/value-object-pattern.html

另一答案

听起来像你所描述的正是Blaze-Persistence Entity Views所做的。当前版本仅支持创建读取模型,即您要发送给客户端的模型,但写模型部分几乎完成。实体视图在接口/抽象类DTO表示和实体模型之间映射。该库充分利用映射信息来实现各种性能优化。

以上是关于JPA的模式:从实体生成数据传输对象DTO并将DTO合并到数据库的主要内容,如果未能解决你的问题,请参考以下文章

具有业务对象、DTO 和实体/域对象的数据转换模式

从 JPA 注释的实体类自动生成数据模式

是否有任何工具可以从实体生成 DTO?

Spring Data JPA 原生查询结果实体

将 DTO 转换为实体,反之亦然

Spring Boot,决定为 REST 和 JPA 分别创建 DTO 对象