从API模型设计DTO

时间:2017-07-15 23:35:01

标签: java spring spring-boot api-design

我正在为一些社交网络后端设计一个使用Spring启动的API。我目前的模型看起来像这样:

public class User {

    private long id;
    private String handle;
    private String name;
    private List<User> followers;
    private List<User> following;

    // Getters setters etc

现在,我创建了与上述结构非常相似的DTO。我的问题是,有时候我想要准确地返回上面的内容(这很好),但有时候,我不希望这样。

例如,当某人只对寻找用户的关注者感兴趣时,我不想包含关注者和关注者(我只是对idhandlename感兴趣为所有这些用户计算followersfollowing将会浪费大量资源。

在我当前的实现中,这些字段返回null个值,我认为这不是一个好主意。我是否应该创建一个单独的DTO而不包含idhandlename的列表?或者有更优雅的方式来做它?

2 个答案:

答案 0 :(得分:3)

这是一个有争议的问题。如果您不想创建单独的dto,有几种方法可以执行此操作。这取决于您将使用的数据访问方法:

使用Spring Data JPA可以在投影中返回实体。您只需要向实体添加一个额外的构造函数:

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("select new User(u.id,u.name) from User u")
    List<User> findAllUserItems();
}

或者使用JPA EntityManger:

    public List<User> findAllUserItems() {
        return entityManager.createQuery("select new User(u.id,u.name) from User u", User.class)
                .getResultList();
    }

如果您想知道不必要的空字段并且您正在使用Jackson,则可以配置为忽略空字段。对于Spring Boot:

spring.jackson.default-property-inclusion=non_null

或者使用Java配置:

    @Bean
    public Jackson2ObjectMapperBuilder objectMapperBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        return builder;
    }

或者不是Spring Boot项目:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(converter());
    }

    @Bean
    public HttpMessageConverter converter() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return new MappingJackson2HttpMessageConverter(objectMapper);
    }
}

另外,如果你打算使用Hibernate Session。要直接映射到dto,您可以使用AliasToBeanResultTransformer

  public List<UserDto> findAllUserItems() {
            return session.createQuery("select u.id as id,u.name as name from User u")
                    .setResultTransformer(Transformers.aliasToBean(UserDto.class))
                    .list();
 }

答案 1 :(得分:0)

假设您可以尝试这样做。

@Entity
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @ManyToOne
    private User parent;

    @OneToMany(mappedBy="parent")
    private List<User> followers;

    @OneToMany(mappedBy="parent")
    private List<User> following;

    // Getters, Setters etc....
}

post可能会有所帮助。