API 模型的 DTO 设计
Design of DTO from Model for an API
我正在为某些社交网络后端设计一个使用 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。我的问题是,有时我想要 return 上面的内容(这很好)但有时,我不想那样。
例如,当某人只对查找用户的关注者感兴趣时,我不想包括关注者和关注(我只对 id
、handle
和 [=14= 感兴趣] 所以为所有这些用户计算 followers
和 following
将是一种难以置信的资源浪费。
在我当前的实现中,这些字段 return 具有 null
值,我认为这不是一个好主意。我是否应该创建一个单独的 DTO,而不包含那些只有 id
、handle
和 name
的列表?或者有更优雅的方法吗?
假设你可以这样尝试。
@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 可能会有帮助。
这是一个有争议的问题。如果您不想创建单独的 dto,有几种方法可以做到。这取决于您要使用的数据访问方法:
使用 Spring Data JPA 可以 return 投影中的实体。您只需要向您的实体添加一个额外的构造函数:
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 引导:
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引导项目:
@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();
}
我正在为某些社交网络后端设计一个使用 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。我的问题是,有时我想要 return 上面的内容(这很好)但有时,我不想那样。
例如,当某人只对查找用户的关注者感兴趣时,我不想包括关注者和关注(我只对 id
、handle
和 [=14= 感兴趣] 所以为所有这些用户计算 followers
和 following
将是一种难以置信的资源浪费。
在我当前的实现中,这些字段 return 具有 null
值,我认为这不是一个好主意。我是否应该创建一个单独的 DTO,而不包含那些只有 id
、handle
和 name
的列表?或者有更优雅的方法吗?
假设你可以这样尝试。
@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 可能会有帮助。
这是一个有争议的问题。如果您不想创建单独的 dto,有几种方法可以做到。这取决于您要使用的数据访问方法:
使用 Spring Data JPA 可以 return 投影中的实体。您只需要向您的实体添加一个额外的构造函数:
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 引导:
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引导项目:
@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();
}