Hibernate DTO对实体和实体对DTO

Hibernate DTO对实体和实体对DTO,hibernate,domain-driven-design,dozer,Hibernate,Domain Driven Design,Dozer,我们将使用DTO向表示层发送数据和从表示层发送数据。 我们有如下几层: 门面 应用服务 领域 我们使用推土机帮助我们将实体转换为dto。 但我现在有两个问题: 从实体到dto,我们可以使用推土机,但从dto到实体,我们可以使用推土机吗?如果是,如何进行 我应该在哪里创建实体?在门面还是DTOAsembler 例如,我必须注册一本书。书本实体看起来像: 我们有一个数据传感器: BookDTOAssembler{ BookDTO toDAO(bookEntity){ ... }

我们将使用DTO向表示层发送数据和从表示层发送数据。 我们有如下几层:

  • 门面
  • 应用服务
  • 领域
我们使用推土机帮助我们将实体转换为dto。 但我现在有两个问题:

  • 从实体到dto,我们可以使用推土机,但从dto到实体,我们可以使用推土机吗?如果是,如何进行
  • 我应该在哪里创建实体?在门面还是DTOAsembler 例如,我必须注册一本书。书本实体看起来像:

    我们有一个数据传感器:

    BookDTOAssembler{
    
      BookDTO toDAO(bookEntity){
      ...
      }
      BookEntiy fromDTO(book DTO,BookRepository bookRepository){
        //1.Where should i create book entity? 
        //2.Is there any effective way to convert dto to entity in java world?
      }
    }
    
    选项1

    the BookManagedFacade has a registerBook function:
    public registerBook(bookDTO){
       Book book = BookDTOAssembler.fromDTO(book DTO);
    }
    
    //Create book in BookDTOAssembler.fromDTO 
    public static BookEntiy fromDTO(BookDTO bookDTO,BookRepository bookRepository){
        //book is never registered 
        if (0==bookDTO.getBookID()){
           Book book = new Book(bookRepository.generateNextBookNumber(),bookDTO.getName());
        }else{
           //book is been registed so we get it from Repository
           book = bookRepository.findById(bookDTO.getBookID()); 
        }
        book.setAuthor(bookDTO.getAuthor);
        ...
        return book;
    }
    
    选项2

    the BookManagedFacade has a registerBook function:
    public registerBook(bookDTO){
       Book book = new Book(bookRepository.generateNextBookNumber(),bookDTO.getName());
       book = BookDTOAssembler.fromDTO(book DTO,book);
    }
    
    //add another function in BookDTOAssembler.fromDTO 
    public static BookEntiy fromDTO(BookDTO bookDTO,Book book){
        book.setAuthor(bookDTO.getAuthor);
        ...
        return book;
    }
    

    有一个更好?或者它可以以更好的方式实现。

    通常不将对象(域实体的DTO表示)传输回服务器。因为如果这样做,就会破坏封装,因为任何人都可以对DTO应用更改,然后将信息发送回

    相反,您应该创建一个用于修改对象的服务接口,因为它允许服务器对其模型应用更改

    因此,服务实际上分为两部分:

  • 用于获取所有实体的数据表示的查询部分
  • 用于将更改应用于实体的命令部分

  • 坦白说,我会远离推土机。我们在我当前的项目中使用它,我讨厌它:它迫使您手动执行某些操作,或者通过添加不应该存在的setter来完全破坏对象的封装。无论如何,有些操作必须在没有它的情况下进行。最大的问题是:如果您碰巧重命名了一个属性,那么一切都可以正常编译,但只会在运行时产生错误的结果。将DTO转换为实体或将DTO转换为实体是乏味的,但很简单。手动操作可以确保封装被保留,并允许重构。这是真的!如果有任何更改,可以在运行时找到它!关于我的问题2,你有什么建议?我更喜欢使用一种只从BookDTO复制到Book的方法,而不在乎书从哪里来。你更喜欢fromDTO(BookDTO BookDTO,Book Book Book)?关于运行时错误-你可以编写实体间转换的测试/dto。回答不错。我同意。但是,我认为您发送回服务器的仍然是DTO。不同之处在于,您不会将DTO映射回域实体。相反,正如您所说,DTO代表您希望应用于现有实体的命令。对于创建新实体的命令,DTO将提供创建所述实体所需的数据。是的。我只是说,你不应该发送一个DTO来表示域实体中的所有信息。是的,我知道你在谈论cqrs。但现在,我们没有cqrs实现。所以。如果我在书中有很多属性,如何将这些属性传递到服务接口?或者我应该提供像'updateName(),updateAuthor()…Updatexx'这样的接口,然后客户端逐个调用这个接口吗?
    the BookManagedFacade has a registerBook function:
    public registerBook(bookDTO){
       Book book = new Book(bookRepository.generateNextBookNumber(),bookDTO.getName());
       book = BookDTOAssembler.fromDTO(book DTO,book);
    }
    
    //add another function in BookDTOAssembler.fromDTO 
    public static BookEntiy fromDTO(BookDTO bookDTO,Book book){
        book.setAuthor(bookDTO.getAuthor);
        ...
        return book;
    }