DTO 模式:在两个对象之间复制属性的最佳方式

新手上路,请多包涵

在我的应用程序架构中,我通常通过服务层将对象或对象列表从数据访问层发送到 Web 层,在服务层中,这些对象从 DAO 对象转换为 DTO 对象,反之亦然。 Web 层无权访问 DAO 对象,并且 DAO 层不使用 DTO。

为了演示,我通常把代码写成:

 @Transactional(readOnly = true)
public List<UserDTO> getAllUserAsUserDTO() {
    List<UserDTO> userDTOs = new ArrayList<UserDTO>();

    for(User user : getAllUser()) {
        userDTOs.add(constructUserDTO(user));
    }

    return userDTOs;
}

private UserDTO constructUserDTO(User user) {
    UserDTO userDTO = new UserDTO();
    userDTO.setFullName(user.getFullName());
    userDTO.setId(user.getId());
    userDTO.setUsername(user.getUsername());
    userDTO.setRole(user.getRole());
    userDTO.setActive(user.isActive());
    userDTO.setActiveText(user.isActive() ? "Active" : "Inactive");
    return userDTO;
}

这里的用户是数据库实体:

 @javax.persistence.Entity
@Table(name = "USER")
public class User extends Entity {

    @Transient
    private static final long serialVersionUID = -112950002831333869L;

    private String username;
    private String fullName;
    private boolean active;
    private String role;
    // other fields

    public User() {
        super();
    }

    @NaturalId
    @Column(name = "USERNAME", nullable = false)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(name = "FULL_NAME")
    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    @Column(name = "ACTIVE", nullable = false)
    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    @Column(name = "ROLE")
    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

这是 UserDTO:

 public class UserDTO extends BaseDTO {

    private static final long serialVersionUID = -3719463614753533782L;

    private String username;
    private String fullName;
    private String role;
    private String activeText;
    private Boolean active;
    //other properties

    public UserDTO() {
        super();
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getActiveText() {
        return activeText;
    }

    public void setActiveText(String activeText) {
        this.activeText = activeText;
    }

    public Boolean getActive() {
        return active;
    }

    public void setActive(Boolean active) {
        this.active = active;
    }
}

所以我想知道这是否是在两个对象之间复制属性的唯一方法。我想我不确定。此外,我正在使用 lambdaj ,那么此 API 中是否有一种方法可以复制所有这些属性以创建其他对象的列表?

这个话题可能听起来很主观,但我真的很想从你们这些专家那里知道,在最大字段具有相同字符串的情况下,如何将对象从一种形式转换为另一种形式。

原文由 Tapas Bose 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

你可以看看 推土机,它是

Java Bean 到 Java Bean 映射器,递归地将数据从一个对象复制到另一个对象。通常,这些 Java Bean 将具有不同的复杂类型。

另一个更好的链接…

原文由 pgras 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以使用 Apache Commmons Beanutils 。 API是

org.apache.commons.beanutils.PropertyUtilsBean.copyProperties(Object dest, Object orig)

对于属性名称相同的所有情况,它将属性值从“源”bean 复制到“目标”bean。

现在我要跑题了。使用 DTO 通常被认为是 EJB3 中的反模式。如果你的 DTO 和你的域对象非常相似,那么真的没有必要重复代码。 DTO还是有优点的,尤其是在涉及到远程访问时节省网络带宽。我没有关于您的应用程序架构的详细信息,但如果您谈到的层是逻辑层并且不跨网络,我认为不需要 DTO。

原文由 Lan 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题