ページの操作と@ManyToMany
マッピングは本当に簡単な作業です。
最初にここにあなたのモデルと類似したモデルがあります(基本的には@Id
と@GeneratedValue
というアノテーションが追加されてデータベース識別子が生成されます)。
ポストエンティティ:
package com.example.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
@Entity
public class Post {
@Id
@GeneratedValue
private long id;
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinTable(joinColumns = @JoinColumn(name = "post_id"), inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags = new HashSet<>();
public Set<Tag> getTags() {
return tags;
}
}
タグエンティティ:
package com.example.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Tag {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "tags")
private List<Post> posts = new ArrayList<Post>();
public void setName(String name) {
this.name = name;
}
}
今、あなたはポストエンティティをフェッチするPagingAndSortingRepository
が必要になります。pagablesでの作業
package com.example.repository;
import java.util.Set;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.Post;
@Repository
public interface PostRepository extends PagingAndSortingRepository<Post, Long> {
@Transactional(readOnly = true)
Set<Post> findByTagsName(String name);
@Transactional(readOnly = true)
Page<Post> findByTagsName(String name, Pageable pageable);
}
は同じくらい簡単です。通常のSpring Data JPAファインダメソッドを記述します。割り当てられたタグエンティティの名前で投稿を検索する場合は、findBy Tags
+ Name
などのフィールド名を連鎖させて、通常のファインダを作成してください。これにより、JPQLのアプローチSELECT p FROM Post p JOIN FETCH p.tags t WHERE t.name = :tagName
に似たクエリが作成されます。タグ名のパラメータをメソッドのパラメータとして渡します。
Pageableサポートを追加する場合は、Pageable
というパラメータを2番目のパラメータとして追加し、戻り値をSet
の代わりにPage
に変更します。それで全部です。少なくともここ
は、コードを確認するためにいくつかのテストは以下のとおりです。
package com.example.repository;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.Post;
import com.example.model.Tag;
@RunWith(SpringRunner.class)
@Transactional
@SpringBootTest
public class PostRepositoryTests {
@Autowired
private PostRepository postRepository;
@PersistenceContext
private EntityManager entityManager;
@Test
public void receiveMultiplePostsWithTagsByName() {
final String nameA = "A";
final String nameB = "B";
final String nameC = "C";
final String nameD = "D";
final String nameE = "E";
final Tag tagA = new Tag();
tagA.setName(nameA);
final Tag tagB = new Tag();
tagB.setName(nameB);
final Tag tagC = new Tag();
tagC.setName(nameC);
final Tag tagD = new Tag();
tagD.setName(nameD);
final Tag tagE = new Tag();
tagE.setName(nameE);
final Post postOne = new Post();
postOne.getTags().add(tagA);
postOne.getTags().add(tagB);
postRepository.save(postOne);
final Post postTwo = new Post();
postTwo.getTags().add(tagA);
postTwo.getTags().add(tagB);
postTwo.getTags().add(tagE);
postRepository.save(postTwo);
final Post postThree = new Post();
postThree.getTags().add(tagA);
postThree.getTags().add(tagB);
postThree.getTags().add(tagC);
postThree.getTags().add(tagE);
postRepository.save(postThree);
entityManager.flush();
entityManager.clear();
final Set<Post> tagsByA = postRepository.findByTagsName(nameA);
assertThat("Expected three hits!", tagsByA, hasSize(3));
final Set<Post> tagsByB = postRepository.findByTagsName(nameB);
assertThat("Expected three hits!", tagsByB, hasSize(3));
final Set<Post> tagsByC = postRepository.findByTagsName(nameC);
assertThat("Expected one hit!", tagsByC, hasSize(1));
final Set<Post> tagsByD = postRepository.findByTagsName(nameD);
assertThat("Expected no hits!", tagsByD, empty());
final Set<Post> tagsByE = postRepository.findByTagsName(nameE);
assertThat("Expected two hits!", tagsByE, hasSize(2));
}
@Test
public void receiveMultiplePostsWithTagsByNamePaged() {
final String nameA = "A";
final Tag tagA = new Tag();
tagA.setName(nameA);
final Post postOne = new Post();
postOne.getTags().add(tagA);
postRepository.save(postOne);
final Post postTwo = new Post();
postTwo.getTags().add(tagA);
postRepository.save(postTwo);
final Post postThree = new Post();
postThree.getTags().add(tagA);
postRepository.save(postThree);
final Post postFour = new Post();
postFour.getTags().add(tagA);
postRepository.save(postFour);
final Post postFive = new Post();
postFive.getTags().add(tagA);
postRepository.save(postFive);
entityManager.flush();
entityManager.clear();
final Page<Post> tagsByAFirstPageSize2 = postRepository.findByTagsName(nameA, new PageRequest(0, 2));
assertThat("Expected two page items!", tagsByAFirstPageSize2.getContent(), hasSize(2));
assertThat("Expected five items in sum!", tagsByAFirstPageSize2.getTotalElements(), is(5L));
assertThat("Should be first page!", tagsByAFirstPageSize2.isFirst(), is(true));
assertThat("Should not be last page!", tagsByAFirstPageSize2.isLast(), is(false));
final Page<Post> tagsBySecondPageSize2 = postRepository.findByTagsName(nameA, new PageRequest(1, 2));
assertThat("Expected two page items!", tagsBySecondPageSize2.getContent(), hasSize(2));
assertThat("Expected five items in sum!", tagsBySecondPageSize2.getTotalElements(), is(5L));
assertThat("Should not be first page!", tagsBySecondPageSize2.isFirst(), is(false));
assertThat("Should not be last page!", tagsBySecondPageSize2.isLast(), is(false));
final Page<Post> tagsByLastPageSize2 = postRepository.findByTagsName(nameA, new PageRequest(2, 2));
assertThat("Expected one last page item!", tagsByLastPageSize2.getContent(), hasSize(1));
assertThat("Expected five items in sum!", tagsByLastPageSize2.getTotalElements(), is(5L));
assertThat("Should not be first page!", tagsByLastPageSize2.isFirst(), is(false));
assertThat("Should be last page!", tagsByLastPageSize2.isLast(), is(true));
}
}
私はあなたが '私が使用したい[春-データ-JPA]' –
@RobertNiestroj [春・データを使用している場所を確認いけません-jpa]リポジトリインタフェースメソッドの宣言ですが、limitとJOINを持つJPQLをサポートしているようには見えません。あるいは、[em]を使ってカスタムメソッドを実装しました。うまくいけば、再利用可能な[Page]型を返します。だから、私は正しいことをしているのだろうか。ありがとうございました。 – nasiajai