簡體   English   中英

Spring Data JPA - 多對多查詢

[英]Spring Data JPA - Many to many query

我有兩個實體 Person 和 Movie。

@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 data jpa 但找不到正確的查詢。

實體關系的最佳實踐:

  1. 始終使用fetch = FetchType.LAZY
  2. 當您也想獲取關系的另一面時,請使用JOIN FETCH Query。
    這也解決了休眠的LazyInitializationException
  3. 始終使用spring.jpa.open-in-view=false

例子:
由 Spring Data JPA 和 Hibernate 作為 JPA 提供者。

實體:

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);
    }

}

由於您使用的是 Fetch 類型lazy,因此您需要使用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/

您可以直接使用 join :

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

列表 findPersonH​​asMovie();

您只需要在 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM