atul
atul

Reputation: 66

Lazy loading not working with Specification

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

Answers (2)

Rahul Sawant
Rahul Sawant

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

JPA Doc

Upvotes: 0

fg78nc
fg78nc

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

Related Questions