当前位置: 首页 > 知识库问答 >
问题:

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

颜云瀚
2023-03-14

在我的应用程序架构中,我通常通过服务层将对象或对象列表从数据访问层发送到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;
    }
}

这是用户DTO:

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中是否有一种方法可以复制所有这些属性以创建其他对象的列表?

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

共有3个答案

莘康裕
2023-03-14

我有一个需要从JPA实体转换到d to的应用程序,我想了想,最终提出使用< code > org . spring framework . beans . bean utils . copy properties 复制简单属性,并扩展和使用< code > org . spring framework . binding . convert . service . defaultconversionservice 转换复杂属性。

具体来说,我的服务是这样的:

@Service("seedingConverterService")
public class SeedingConverterService extends DefaultConversionService implements ISeedingConverterService  {
    @PostConstruct
    public void init(){
        Converter<Feature,FeatureDTO> featureConverter = new Converter<Feature, FeatureDTO>() {

            @Override
            public FeatureDTO convert(Feature f) {
                FeatureDTO dto = new FeatureDTO();
                //BeanUtils.copyProperties(f, dto,"configurationModel");
                BeanUtils.copyProperties(f, dto);
                dto.setConfigurationModelId(f.getConfigurationModel()==null?null:f.getConfigurationModel().getId());
                return dto;
            }
        };

        Converter<ConfigurationModel,ConfigurationModelDTO> configurationModelConverter = new Converter<ConfigurationModel,ConfigurationModelDTO>() {
            @Override
            public ConfigurationModelDTO convert(ConfigurationModel c) {
                ConfigurationModelDTO dto = new ConfigurationModelDTO();
                //BeanUtils.copyProperties(c, dto, "features");
                BeanUtils.copyProperties(c, dto);
                dto.setAlgorithmId(c.getAlgorithm()==null?null:c.getAlgorithm().getId());
                List<FeatureDTO> l = c.getFeatures().stream().map(f->featureConverter.convert(f)).collect(Collectors.toList());
                dto.setFeatures(l);
                return dto;
            }
        };
        addConverter(featureConverter);
        addConverter(configurationModelConverter);
    }
}
牧熙云
2023-03-14

你可以看看推土机,它是一个

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

另一个更好的链接…

邬阳
2023-03-14

可以使用Apache Commmons Beanutils。该API是

< code > org . Apache . commons . bean utils . property utils bean . copy properties(Object dest,Object orig)。

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

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

 类似资料:
  • 问题内容: 在我的应用程序体系结构中,我通常将对象或对象列表从数据访问层通过服务层发送到Web层,在服务层中,这些对象从DAO对象转换为DTO对象,反之亦然。Web层无法访问DAO对象,并且DAO层不使用DTO。 为了演示,我通常将代码编写为: 这里的用户是数据库实体: 这是UserDTO: 所以我想知道这是否是在两个对象之间复制属性的唯一方法。我想我不确定。另外,我也在使用lambdaj,因此此

  • 假设您有分层数据,并且希望获得单独属性的合并值,那么最优雅的,或者说groovy的方法是什么呢?

  • 可能重复: Java两个字段排序问题 我有用户对象,比如 我有一个,其中包含这些对象,我必须按名字对其进行排序,如果名字匹配,则只按姓氏排序。

  • 我试图执行两个WordPress分类法之间的查询。我将使用的分类法是品牌和product_cat。 预期结果是在下拉列表中显示所有现有品牌作为父亲和每个品牌的所有现有产品类别作为儿童* 我最初尝试的是迭代所有产品,询问它们的类别和品牌,形成一个关联数组;但这最终导致了PHP致命错误:允许的内存大小为268435456字节,因为它们是数据库中的10000个产品。这就是我使用的代码: 当我说“现有品牌

  • 我从0开始开发我的项目已经1年了。我的框架和测试已经达到了一定的“维护”水平。然而,每天我都在怀疑我是否在我的项目中使用了良好的实践。如果有经验的人能回答我的几个问题就好了。我主要对页面对象模式和页面工厂有疑问。 简要说明: 我的项目是一个基于一页的应用程序,用C#,angular编写。js,javascript。驱动程序是一个静态实例,它有很多额外的方法(在下面的代码中,我只展示了2)。每个页面

  • 问题内容: 我们有两个PHP5对象,并希望将其中一个的内容合并到第二个中。它们之间没有子类的概念,因此以下主题中描述的解决方案不适用。 备注: 这些是对象,而不是类。 对象包含很多字段,所以 foreach 会很慢。 到目前为止,我们考虑将对象A和B转换为数组,然后在重新转换为对象之前使用 array_merge() 合并它们,但是我们不能为此感到骄傲。 问题答案: 如果您的对象仅包含字段(没有方