如何使用 Spring Data 获取数据

Posted

技术标签:

【中文标题】如何使用 Spring Data 获取数据【英文标题】:How to Fetch Data using Spring Data 【发布时间】:2015-09-03 19:12:30 【问题描述】:

嘿,我想创建一个扩展 JpaRepository 的存储库并在不编写实际查询的情况下获取结果, 在我的示例中,我有 2 个表 Book 和 Author 由多对多关系映射,假设我想按特定 author_id 获取书籍列表,因为在我的书籍实体中,我没有任何名为 author_id 的字段,所以我将如何使用 JPARepository 获取结果而不编写实际查询。 我正在做这样的事情:我创建了一个包含 Book 和 Author 对象的 bookDTO,我创建了扩展 JpaRepository 的 bookDTORepository 并调用了 List<Book> findByAuthor_Id(Integer id); ,但它的抛出错误为:Not an managed type: class golive.data.bookdto 我的书类是

package golive.data;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
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;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sun.istack.internal.NotNull;

@Entity
@Table(name="book")
public class Book implements java.io.Serializable

	@Id
	@GeneratedValue
	private Integer id;
	
	@NotNull
	@Column(name="name")
	private String name;


	@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
	@JoinTable(name = "writes", joinColumns =  @JoinColumn(name = "book_id") , inverseJoinColumns =  @JoinColumn(name = "author_id") )
	private Set<Author> authors = new HashSet<Author>(); 


	public Set<Author> getAuthors() 
		return authors;
	

	public Integer getId() 
		return id;
	

	public String getName() 
		return name;
	

	public void setAuthors(Set<Author> authors) 
		this.authors = authors;
	

	public void setId(Integer id) 
		this.id = id;
	

	public void setName(String name) 
		this.name = name;
	
	
	

我的作者类别是

package golive.data;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
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;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sun.istack.internal.NotNull;

@Entity
@Table(name="author")
public class Author implements java.io.Serializable

	@Id
	@GeneratedValue
	@Column(name="id")
	private Integer Id;
	
	@NotNull
	@Column(name="name")
	private String name;


	public Integer getId() 
		return Id;
	

	public String getName() 
		return name;
	



	public void setId(Integer id) 
		Id = id;
	

	public void setName(String name) 
		this.name = name;
	
	

我的 bookdto 课程是

package golive.data;

public class bookdto 

	private Book book;
	private Author author;
	public Book getBook() 
		return book;
	
	public void setBook(Book book) 
		this.book = book;
	
	public Author getAuthor() 
		return author;
	
	public void setAuthor(Author author) 
		this.author = author;
	
	
我的书 DTORepository 是:

package golive.data;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

public interface bookDTORepository extends JpaRepository<bookdto, Book> 
	
	List<Book> findByAuthor_Id(Integer id);
	

我的书控制器方法,我补充说:

	@RequestMapping(value = "/listbyauthor", method = RequestMethod.POST, produces = "application/json")
	public ResponseEntity<List<Book>> getBookByAuthorId(@RequestBody Author author,HttpServletResponse response) 
		try 
			Author temp = new Author();
			temp.setId(author.getId());
			temp.setName(author.getName());
			return new ResponseEntity<>(bookRepository.findByAuthor(temp), HttpStatus.OK);
		 catch (Exception e) 
			e.printStackTrace();
		
		return new ResponseEntity<>(HttpStatus.NO_CONTENT);
	

【问题讨论】:

【参考方案1】:

您想查找特定作者的所有书籍,因此,给定一个作者,检索其作者集包含指定作者的所有书籍。

相关的 JPQL 运算符为:

http://www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_

[NOT] MEMBER [OF] [NOT] MEMBER OF 运算符检查指定的 元素包含在指定的持久集合字段中。

例如:

'English' MEMBER OF c.languages 是 TRUE 如果语言包含 'English' 如果不是,则为 FALSE。 'English' NOT MEMBER OF c.languages 是 如果语言不包含“英语”,则为 TRUE。

您可能(或可能不)知道,您正在使用 Spring Data,它可以根据方法名称为您派生一些查询。然而,文档没有提到对 [NOT] MEMBER [OF] 运算符的支持:

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

因此,您需要向您的存储库添加一个自定义查询方法,如下所示:

public interface BookRepository extends JpaRepository<Book, Integer> 

    @Query("select b from Book b where ?1 MEMBER OF b.authors")
    List<Book> findByAuthor(Author author);

其中作为参数传递的作者是从数据库中检索到的持久实例(通过您的 AuthorRepository)。

【讨论】:

我按照你上面说的做了,错误来了:object references an unsaved transient instance - save the transient instance before flushing: golive.data.Author 如何创建/获取作为参数传递的作者?请注意答案底部的粗体注释。 我刚刚添加了我的请求映射方法一次看看它是否正确 不,从数据库中检索作者,如答案中明确说明的那样。因此,像上面一样创建一个 Author Repository 定义,但为 Authors 并使用继承的 findOne(..) 方法来获取现有的持久实例。

以上是关于如何使用 Spring Data 获取数据的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA:查询ManyToMany,如何从映射类中获取数据?

如何在本机查询中使用 NVL 或 COALESCE 获取 Spring Data JPA 中的值列表

如何使用 Spring Data MongoDB 通过 GridFS ObjectId 获取二进制流

如何在 spring-data 中使用子图(使用休眠)?

Spring data redis - 如何使用 hashOperation 的 scan 方法根据模式获取键或值?

如何在 Spring Data JPA 中使用带有分页的投影接口?