繁体   English   中英

标准 JPA 2 加入多对多单向实体

[英]Criteria JPA 2 join many to many unidirectional realtion

我有两个实体,电影和流派,从流派到电影具有多对多关系。 流派是关系的“父母”。
这会生成三个表: genremoviegenre_movie

@Entity
public class Genre {
  @Id
  @GeneratedValue(strategy = AUTO)
  private Long id;

  @ManyToMany(fetch = LAZY)
  @JoinTable( name = "genre_movie",
    joinColumns = {@JoinColumn(name = "genre_id")},
    inverseJoinColumns = {@JoinColumn(name = "movie_id")}
  )
  private Set<Movie> movies = new HashSet<>();

  ...
}


@Entity
public class Movie {
  @Id
  @GeneratedValue(strategy = AUTO)
  private Long id;
  ...
}

实体图

我可以使用条件查询 api 执行此查询吗? 根据流派 ID 过滤电影。

select *
from movie
  join genre_movie on movie.id = genre_movie.movie_id
where genre_id = 19;

解决方案

在电影方面双重映射您的 MovieGenre:

@ManyToMany(fetch = LAZY, mappedBy = "movies")
private Set<Genre> genres = new HashSet<>();

这不会创建额外的表,但(只是)使关联在“电影端”上可用(对于 JPA);;)


..然后我们可以查询(像往常一样,未经测试):

-- e.g. JPQL:
select [distinct] movie
from Movie movie
join movie.genres genre
where genre.id = :pGenreId

..传入Genre ID。 或者:

select [distinct] movie
from Movie movie
where :pGenre member of movie.genres

...通过Genre object(参数)。


也可以看看:

这是不可能的,因为 Movie 实体没有对 Genre 的引用,因为它不是双向的。

但是您可以重组查询以获得相同的结果:

Select * from genre
  inner join genre_movie on genre.id = genre_movie.genre_id
  inner join movie on genre_movie.movie_id = movie.id
  where genre.genre_id = 19;

查询将按如下方式实现:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Movie> cq = cb.createQuery(Movie.class);

Root<Genre> rootGenre = cq.from(Genre.class);
Join<Genre,Movie> joinMovie = rootGenre.join("movies");
//Join<Genre,Movie> joinMovie = rootGenre.join(Genre_.movies);

cq.select(joinMovie);
cq.where(cb.equals(rootGenre.get("id"), 19));
//cq.where(cb.equals(rootGenre.get(Genre_.id), 19));

return this.em.createQuery(cq).getResultList();

我特别推荐使用元模型(注释行),因为在按字符串格式的名称访问属性时,可能会出现错误,而元模型不在更复杂的查询中。

我还认为将关系定义为双向以便能够将电影 class 设置为 Root 会很有趣

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM