与页面和@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
来获取帖子实体:
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
的参数添加为第二个参数,并将返回值转换为
Page
而不是
Set
。就是这样。
至少以下是一些测试来验证代码:
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));
}
}
[spring-data-jpa]
。 - Robert Niestroj