我是从与其他实体上具有ManytoOne关系的实体查询数据。 使用规范能够获取唯一的根记录。但是我也需要从关系实体中获取该列。
我是Spring Boot的新手,正在尝试构建API。
查询根始终引用实体,然后引用规范中的自定义查询。
return new Specification<CallMessage>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<CallMessage> root,
CriteriaQuery<?> query, CriteriaBuilder cb)
{
List<Predicate> predicates = new ArrayList<>();
In<Long> inClause = cb.in(root.get("bed_address"));
inClause.value("XYZ");
predicates.add(inClause);
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
}
@Entity(name = "calls")
public class CallMessage implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@OneToMany(targetEntity = PresetModel.class, mappedBy = "id", orphanRemoval = false)
private Set<PresetModel> presetModels;
}
@Entity(name = "reports_preset_filter")
public class PresetModel extends AuditModel{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
private String preset_name;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name="call_id" ,nullable=false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private CallMessage callMessage ;
}
尽管使用JpaSpecificationExecutor不能使用另一个查询来联接这两个表。它可以通过任何方式获取记录,例如- call_message { 编号:1 report_preset_filter:[ ] }
我正在尝试使用多个谓词构建过滤器API,在这里我已经修剪了谓词列表以及其他实体列。
答案 0 :(得分:0)
发生的事情是,默认情况下,JPA @OneToMany
的获取策略是惰性的,这意味着引用字段只是“空”代理,仅当您使用getter显式读取它们时才填充它们。您可能想保留该策略,仅获取此查询的字段。
一个优雅的解决方案是使用实体图创建获取计划:
实体图是特定持久性查询或操作的模板。在创建读取计划或在同一时间检索的持久字段组时使用它们。默认情况下,实体字段或属性是延迟获取的。开发人员将字段或属性指定为获取计划的一部分,持久性提供程序将急切地获取它们。
https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs.htm
这是一个主实体的代码示例,其中包含一些详细信息字段:
@NamedEntityGraph(
name = "post-entity-graph-with-comment-users",
attributeNodes = {
@NamedAttributeNode("subject"),
@NamedAttributeNode(value = "comments", subgraph = "comments-subgraph"),
},
subgraphs = {
@NamedSubgraph(
name = "comments-subgraph",
attributeNodes = {
@NamedAttributeNode("user")
}
)
}
)
@Entity
public class Post {
@Id
private Long id;
private String subject;
@OneToMany(mappedBy = "post")
private List<Comment> comments;
}
@Entity
public class Comment {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
//...
}
然后,您可以覆盖SimpleJpaRepository
子类
@Override
public List<T> findAll(Specification<T> spec, Sort sort, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
TypedQuery<T> query = getQuery(spec, sort);
query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
return query.getResultList();
}
因此要运行Specification
,它还会加载与注释相关的用户:
List<Post> results = myRepository.findAll(mySpecification, EntityGraph.EntityGraphType.LOAD, "post-entity-graph-with-comment-users");