是否应将实体 class 用作请求正文
Should entity class be used as request body
假设我必须保存一个实体,在本例中为 Book。我有下一个代码:
@RestController
@RequestMapping("books")
public class BookController {
@Inject
BookRepository bookRepository;
@PostMapping
public Book saveBook(@RequestBody Book book) {
return bookRepository.save(book);
}
}
我的实体 Book 是一个持久化实体:
@Entity(name = "BOOK")
public class Book{
@Id
@Column(name = "book_id")
private Integer id;
@Column(name = "title")
private String title;
(get/sets...)
}
问题是:在控制器层的 @RequestBody
中使用我的持久性实体是一种不好的做法吗?或者我应该创建一本书 DTO 并将其映射到服务层中的持久性 class?什么更好,为什么?
您应该创建一个 DTO class 并将其映射到持久性 class。参考 this rule description 同样的。指定的原因是
if a persistent object is used as an argument of a method annotated with @RequestMapping, it’s possible from a specially crafted user input, to change the content of unexpected fields into the database
除此之外,使用 DTO 我们可以省略一些我们不希望在表示层中成为 present/visible 的持久对象属性。
您可以将 DTO class 映射到控制器本身中的持久化实体,如下所示。
@RestController
@RequestMapping("books")
public class BookController {
@Autowired
BookRepository bookRepository;
@Autowired
ModelMapper modelMapper
@PostMapping
public Book saveBook(@RequestBody BookDTO modelBook) {
Book book = this.modelMapper.map(modelBook, Book.class);
return bookRepository.save(book);
}
}
ModelMapper 是一个框架,可以执行 DTO 到实体的映射,反之亦然。检查 ModelMapper website.
您可以参考 answer and comments 了解更多相关信息。
是的,这是一个非常糟糕的主意。
实体表示在数据库中维护的持久数据,并封装了企业范围的业务规则。另一方面,DTO 是一个愚蠢的对象——它只包含属性和 getter 和 setter,但没有任何其他重要的逻辑。 DTO 仅用于将数据从应用程序的一个子系统传输到另一个子系统。
假设有一个新的需求来添加新的多对多关系:
@Entity(name = "BOOK")
public class Book{
@Id
@Column(name = "book_id")
private Integer id;
@ManyToMany
Set<Student> likes;
...
}
数据库中的此类更改也会更改 API。
假设我必须保存一个实体,在本例中为 Book。我有下一个代码:
@RestController
@RequestMapping("books")
public class BookController {
@Inject
BookRepository bookRepository;
@PostMapping
public Book saveBook(@RequestBody Book book) {
return bookRepository.save(book);
}
}
我的实体 Book 是一个持久化实体:
@Entity(name = "BOOK")
public class Book{
@Id
@Column(name = "book_id")
private Integer id;
@Column(name = "title")
private String title;
(get/sets...)
}
问题是:在控制器层的 @RequestBody
中使用我的持久性实体是一种不好的做法吗?或者我应该创建一本书 DTO 并将其映射到服务层中的持久性 class?什么更好,为什么?
您应该创建一个 DTO class 并将其映射到持久性 class。参考 this rule description 同样的。指定的原因是
if a persistent object is used as an argument of a method annotated with @RequestMapping, it’s possible from a specially crafted user input, to change the content of unexpected fields into the database
除此之外,使用 DTO 我们可以省略一些我们不希望在表示层中成为 present/visible 的持久对象属性。
您可以将 DTO class 映射到控制器本身中的持久化实体,如下所示。
@RestController
@RequestMapping("books")
public class BookController {
@Autowired
BookRepository bookRepository;
@Autowired
ModelMapper modelMapper
@PostMapping
public Book saveBook(@RequestBody BookDTO modelBook) {
Book book = this.modelMapper.map(modelBook, Book.class);
return bookRepository.save(book);
}
}
ModelMapper 是一个框架,可以执行 DTO 到实体的映射,反之亦然。检查 ModelMapper website.
您可以参考 answer and comments 了解更多相关信息。
是的,这是一个非常糟糕的主意。
实体表示在数据库中维护的持久数据,并封装了企业范围的业务规则。另一方面,DTO 是一个愚蠢的对象——它只包含属性和 getter 和 setter,但没有任何其他重要的逻辑。 DTO 仅用于将数据从应用程序的一个子系统传输到另一个子系统。
假设有一个新的需求来添加新的多对多关系:
@Entity(name = "BOOK")
public class Book{
@Id
@Column(name = "book_id")
private Integer id;
@ManyToMany
Set<Student> likes;
...
}
数据库中的此类更改也会更改 API。