Reputation: 66
I have migrated to spring v2.1.2.RELEASE and using hibernate version 5.3.7.FINAL
We have @OneToOne bi directional relationship between entity as follows
class Parent{
@OneToOne(fetch = FetchType.LAZY, mappedBy = "parent", optional = false)
@NotAudited
private Child child;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}
class Child{
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
@MapsId
@NotNull
private Parent parent;
@Id
@Column(name = "indent_id", insertable = false, updatable = false)
private Integer parentId;
}
calling
parentRepository.findByIdIn(Collections.singletonList(1));
makes db call as: Hibernate:
select parent0_.id as id1_19_ from parent parent0_ where parent0_.id in (?)
Which is working fine, now consider use case,
public class Filter implements Specification<Parent> {
@Override
public Predicate toPredicate(Root<Indent> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
// TODO Auto-generated method stub
List<Integer> parentIdList = new ArrayList<>();
parentIdList.add(1);
ArrayList<Predicate> predicates = new ArrayList<>();
predicates.add(root.get("id").in(parentIdList));
return predicates.size() == 0 ? null
: criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}
PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.Direction.DESC, "id");
Filter filter = new Filter();
Page<Indent> indentPage = indentRepository.findAll(filter, pageRequest);
makes DB call to Child entity as well
Hibernate:
select parent0_.id as id1_19_ from parent parent0_ where parent0_.id in (?)
select child0_.parent_id as parent_i1_29_ from child child0_ where child0_.indent_id in (?)
Is there any way to avoid Db call to child entity here?
Upvotes: 1
Views: 2339
Reputation: 1264
JPA provider usually takes fetch type Lazy as a hint, so may be in your case its not considering it at all. check below
fetch public abstract FetchType fetch (Optional) Defines whether the value of the field or property should be lazily loaded or must be eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime that the value must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime. If not specified, defaults to EAGER. Default: EAGER
Upvotes: 0
Reputation: 5232
You can define an entity graph to specify a pattern that can be passed to a query to determine which attributes you want to be fetched. Attributes that are not included in the graph will be treated as LAZY by persistence provider.
@Entity
@NamedEntityGraph(name = "only_id", attributeNodes={@NamedAttributeNode("id")})
class Parent{
@OneToOne(fetch = FetchType.LAZY, mappedBy = "parent", optional = false)
@NotAudited
private Child child;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}
JPA API:
EntityGraph entityGraph = entityManager.getEntityGraph("only_idh");
// define your query
query.setHint("javax.persistence.fetchgraph",graph);
More details : https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm
With Spring Data JPA
public interface MyRepository extends JpaRepository<Parent, Integer> {
@EntityGraph(value = "only id")
Parent findById(Integer id)
More details : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.entity-graph
JpaSpecificationExecutor :
public interface MyRepository extends JpaSpecificationExecutor<Parent> {
@Override
@EntityGraph(attributePaths = {"only_id"}, type=EntityGraphType.FETCH)
Parent findByOne(Specification<Parent> spec);
}
More details : https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaSpecificationExecutor.html
Upvotes: 1