使用规范作为查询从@Entity以及关系表中获取记录

时间:2019-08-26 12:13:43

标签: spring-boot spring-boot-jpa

我是从与其他实体上具有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,在这里我已经修剪了谓词列表以及其他实体列。

1 个答案:

答案 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");

请参见https://www.baeldung.com/jpa-entity-graph