47

私のアプリケーションのアーキテクチャでは、通常、オブジェクトまたはオブジェクトのリストをデータアクセス層からサービス層を介して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;
    }
}

したがって、これが2つのオブジェクト間でプロパティをコピーする唯一の方法であるかどうか疑問に思いました。よくわかりません。また、私はlambdajを使用しているので、これらすべてのプロパティをコピーして他のオブジェクトのリストを作成できるメソッドがこのAPIにありますか?

このトピックは主観的に聞こえるかもしれませんが、最大フィールドが同じ文字列を持っている場合に、ある形式から別の形式へのオブジェクトの変換を実行する方法を専門家から知りたいと思います。

4

6 に答える 6

27

Apache Commons Beanutilsを使用できます。API は

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

プロパティ名が同じであるすべてのケースで、「起点」Bean から「宛先」Bean にプロパティ値をコピーします。

今、私はオフトピックに行きます。DTO の使用は、ほとんどの場合、EJB3 ではアンチパターンと見なされます。DTO とドメイン オブジェクトが非常に似ている場合、コードを複製する必要はまったくありません。DTO には、特にリモート アクセスが関係する場合にネットワーク帯域幅を節約するという利点があります。あなたのアプリケーション アーキテクチャに関する詳細はわかりませんが、あなたが話したレイヤーが論理レイヤーであり、ネットワークを横断しない場合、DTO の必要性はわかりません。

于 2013-03-02T05:02:53.933 に答える
22

あなたはブルドーザーを見ることができます

あるオブジェクトから別のオブジェクトにデータを再帰的にコピーするJavaBeanからJavaBeanへのマッパー。通常、これらのJavaBeanはさまざまな複合型になります。

別のより良いリンク...

于 2013-02-27T16:45:19.460 に答える
7

JPAエンティティから DTOに変換する必要のあるアプリケーションがあり、それについて考えた結果、最終的にorg.springframework.beans.BeanUtils.copyProperties単純なプロパティをコピーするために使用し、複雑なプロパティを拡張しorg.springframework.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);
    }
}
于 2016-02-25T02:48:02.623 に答える
2

リフレクションを使用して、 DAOgetオブジェクト内のすべてのメソッドを検索し、 DTO内の同等のメソッドを呼び出すことができます。これは、そのようなメソッドがすべて存在する場合にのみ機能します。このためのサンプルコードを見つけるのは簡単なはずです。set

于 2013-02-27T16:42:17.080 に答える
2

lambdajのプロジェクト関数はあなたが探していることをしませんか?

次のようになります。

List<UserDTO> userNDtos = project(users, UserDTO.class, on(User.class).getUserName(), on(User.class).getFullName(), .....);

(それに応じてUserDTOのコンストラクターを定義します...)

例については、こちらもご覧ください...

于 2013-03-12T14:23:49.447 に答える