我正在使用 tje JPA 标准 API 创建“IN”查询。我想选择特定类别中的课程。类别应该在查询的 IN 部分结束。
这是课程实体。它引用了 Category 实体,因为每个 Course 都在一个 Category 中。
@Entity
public class Course implements DomainObject {
private Long id;
private Integer version;
private String name;
private Category category;
@Override
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
在我的服务中,我想选择属于某个类别(列表)的课程。
public List<Course> findCourses(CourseFilter filter) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Course> criteriaQuery = criteriaBuilder.createQuery(Course.class);
Root<Course> root = criteriaQuery.from(Course.class);
List<Predicate> predicateList = new ArrayList<Predicate>();
if (!filter.getCategories().isEmpty()) {
Predicate predicate = root.get(Course_.category).in(filter.getCategories());
predicateList.add(predicate);
}
Predicate[] predicates = new Predicate[predicateList.size()];
predicateList.toArray(predicates);
criteriaQuery.where(predicates);
TypedQuery<Course> typedQuery = entityManager.createQuery(criteriaQuery);
return typedQuery.getResultList();
}
当查询在方法的最后一行执行时,它会抛出一个错误:
HTTP Status 500 - Request processing failed; nested exception is
org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.TransientObjectException: object references an unsaved transient instance
save the transient instance before flushing:nl.codebasesoftware.produx.domain.Category;
nested exception is java.lang.IllegalStateException:
org.hibernate.TransientObjectException: object references an unsaved transient instance
save the transient instance before flushing: nl.codebasesoftware.produx.domain.Category
我什至不确定我是否使用正确的方法来创建 IN 查询。我认为标准 API 非常复杂。但在我担心 IN 查询之前,我想知道为什么 Hibernate 会抛出这个 TransientObjectException。filter.getCategories ()调用会产生实际的类别,填充主键 id 等。
添加:
以下是我获取用于稍后获取课程的 Category 实例的方法。这也是一个 DAO 方法,通过 @Controller 方法中的 @Service 调用。
public Category findByName(String name) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Category> query = builder.createQuery(Category.class);
Root<Category> root = query.from(Category.class);
Predicate predicate = builder.equal(root.get(Category_.urlTitle), name);
query.where(predicate);
TypedQuery<Category> typedQuery = entityManager.createQuery(query);
return getSingleResult(typedQuery);
}
因此,Hibernate 告诉我我正在使用以某种方式引用未保存实体的 Category 对象,但我不知道如何。从这个方法返回的 Category 只是一个由 Hibernate 获取的 Category。在将它发送到获取课程的方法之前,我没有对它做任何事情。
这是我的控制器方法:
@RequestMapping(method = RequestMethod.GET, value = "/{categoryUrlName}")
public String setup(@PathVariable("categoryUrlName") String categoryUrlName, Model model){
// Fetch the category
Category category = categoryService.findByName(categoryUrlName);
// if no category found, throw a 404
if(category == null){
throw new ResourceNotFoundException();
}
// Fetch courses in this category
List<Course> courses = courseService.findCourses(category);
model.addAttribute("courses", courses);
model.addAttribute("category", category);
model.addAttribute("mainContent", "content/category");
return "main";
}