Spring Data JPA - 多对多查询

时间:2018-05-21 16:23:49

标签: sql spring jpa spring-data

我有两个实体人物和电影。

@Entity
public class Person {
..some fields

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "actors")
@OrderBy("id")
private Set<Movie> moviesActor = new TreeSet<>();

}

@Entity
public class Movie {
..fields
@JoinTable(name = "actor_movie",
            joinColumns = { @JoinColumn(name = "movie_id") },
            inverseJoinColumns = { @JoinColumn(name = "actor_id") })
    private Set<Person> actors = new TreeSet<>();
}

有很多关系,所以有新的表actor_movie来保持它。我怎样才能让每一个拥有任何电影的人都得到它?所以我想要实现的是获取actor_movie表中存在的每个人。我尝试使用Spring数据jpa但找不到正确的查询。

4 个答案:

答案 0 :(得分:0)

由于您使用的是Letch类型,您需要使用join fetch来获取moviesActor。

您可以将jpql与spring数据一起使用。 我尚未测试下面的查询,但应该可以使用。

public interface PersonRepository extends JpaRepository<Person, Long> { //Long if Person.id is of type Long

  @Query("SELECT p FROM Person p LEFT JOIN FETCH p.moviesActor WHERE size(p.moviesActor) > 0");
  List<Person> findActors1();

  // Or

  @Query("SELECT p FROM Person p JOIN FETCH p.moviesActor");
  List<Person> findActors2();

}

有关jpql size()运算符的更多信息,请访问:https://www.thoughts-on-java.org/jpql/

答案 1 :(得分:0)

您可以直接使用join:

@Query("SELECT p FROM Person p  JOIN  p.moviesActor movie");

列出findPersonH​​asMovie();

答案 2 :(得分:0)

实体关系最佳做法:

  1. 始终使用fetch = FetchType.LAZY
  2. 当您也想获取关系的另一面时,请使用JOIN FETCH查询。
    这也可以解决LazyInitializationException的休眠状态。
  3. 始终使用spring.jpa.open-in-view=false

示例:
由Spring Data JPA和Hibernate作为JPA Provider。

实体:

public class Blog{
   ...
   @ManyToMany(fetch = FetchType.LAZY) //default is LAZY in ManyToMany
    @JoinTable(name="blog_tag",
        joinColumns = @JoinColumn(name = "blog_id"),
        inverseJoinColumns = @JoinColumn(name = "tag_id"))
    @OrderBy //order by tag id
    private Set<Tag> tags = new HashSet<>();

    //2 utility methods in owner side
    public void addTag(Tag tag){
        tags.add(tag);
        tag.getBlogs().add(this);
    }
    public void removeTag(Tag tag){
        tags.remove(tag);
        tag.getBlogs().remove(this);
    }
    
    //override equals & hashcode 

}


public class Tag {
    ...
    @ManyToMany(mappedBy = "tags")
    private Set<Blog> blogs = new HashSet<>();

    //override equals & hashcode 
}

现在,假设您想获取一个包含标签项的博客:

存储库:

@Repository
public interface BlogRepository extends JpaRepository<Blog, Long> {
    @Query("select b from Blog b join fetch b.tags where b.name = :name")
    Blog getBlog(@Param("name") String blogName);
}

服务

public interface BlogService {
    Blog getBlog(String blogName);
}

@Service
public class BlogServiceImpl implements BlogService{

    @Autowired
    private BlogRepository blogRepository;

    @Override
    public Blog getBlog(String blogName) {
        return blogRepository.getBlog(blogName);
    }

}

答案 3 :(得分:-1)

在Person和Movie之间只需要一个JOIN。由于Hibernate抽象出中间表的存在,所以你不必担心它。

所以,使用Spring Data Repository:

class PersonRepository extends CrudRepository<Person, Long> {

    List<Person> findByMoviesActor();
}

使用Jpql:

SELECT person FROM Person person JOIN person.moviesActor movie