[英]Handling relations in POST requests with Spring Data JPA
我有以下实体,每个实体都有一个CrudRepository
:
@Entity
class Movie {
@Id Long id;
@Column String name;
@ManyToOne Person director;
}
@Entity
class Person {
@Id Long id;
@Column String name;
}
我的控制器看起来像这样:
@RestController
@RequestMapping("/movies")
class MovieController {
private MovieRepository movies = ...;
private PersonRepository people = ...;
@PostMapping
public Movie create(@RequestBody MovieRequest request) {
// Get the director
Person director = people.findById(request.directorId);
// Create the new movie
Movie movie = new Movie();
movie.name = request.name;
movie.director = director;
// Save the new movie
return movies.save(movie);
}
}
class MovieRequest {
String name;
Long directorId
}
如您所见, create
方法首先按其id加载director,然后创建新影片并最终保存。 这导致两次访问数据库:第一次检索导演,第二次保存电影。
在这种情况下,这不是一个大问题,但可能存在一个有很多关系的实体,这意味着可能会进行大量查询以实现单个插入。
问题 :我想在单个数据库操作中保存新电影。 有没有办法避免初始人查询? 有没有更好的方法来处理这样的案件?
有没有办法告诉代码至极Person
,它需要涉及到你的新Movie
。 因此,您确实需要执行查询并手动进行关联。
只有当您的端点在创建Movie
的同时创建Person
时,才有可能实现替代方案。 然后,您可以简单地执行2个保存操作或使用CascadeType=ALL
进行单个保存操作。
如果你能够改变你的请求参数,可能是一个不错的选择接收一个完整的Person
的对象,而不是一个accpeting的directorId
。 这样你就可以制作关联movie.director = director;
。
小心这种方法:如果收到的Person
对象没有存储在你的数据库中,你将得到一个例外。
也许你可以为你的Directors
创建一个缓存。 例如,如果您将所有董事保存在Redis中,则可以搜索与收到的directorId
相对应的Director
然后执行关联。
当然,你仍然需要进行第二次操作,但它可能比查询数据库便宜。
这将是丑陋的,但你在请求中有personId,所以你可以用你长的人映射你的电影
class Movie {
@Id Long id;
@Column String name;
@ManyToOne Person director;
@Column(name="PERSON_ID")
long personId;
}
在你的控制器中
movie.setPersonId(request.directorId);
我不认为您的MOVIE
表包含“ DIRECTOR_NAME
”列(假设您遵循第二规范化规则)。 它应该只是 DIRECTOR_ID
。
因此,您可以完全跳过在场景中加载控制器名称(前提是directId与请求的查询参数一起发送)。
既然你(应该有)之间的外键约束 Movie.DIRECTOR_ID
和DIRECTOR.ID
,它会寻找任何约束违例之后,如果你想插入任何DIRECTOR_ID
不存在。 所以你不必担心。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.