3

Given these two entities with a OneToOne relationship (A as owning side holding the B entity id):

@Entity
@Table(name="A")
public class AEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    ...

    @OneToOne(optional = true, cascade = CascadeType.ALL)
    @JoinColumn(name = "bId")
    private BEntity b;

}

@Entity
@Table(name="B")
public class BEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @OneToOne(mappedBy = "b", cascade = CascadeType.ALL, optional = true, fetch = FetchType.LAZY)
private AEntity a;
    ...

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    protected Date someDate;

}

I use a criteria query to get all B entities within a given date:

public class BSpecification {
    public static Specification<BEntity> filter(BFilter filter) {
        return new Specification<BEntity>() {
            @Override
            public Predicate toPredicate(Root<BEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if(filter.getDateFrom() != null){
                    predicates.add(cb.greaterThanOrEqualTo(cb.function("date", Date.class, root.get(BEntity_.someDate)),
                            filter.getDateFrom()));
                }
                if(filter.getDateTo() != null){
                    predicates.add(cb.lessThanOrEqualTo(cb.function("date", Date.class, root.get(BEntity_.someDate)), 
                            filter.getDateTo()));
                }
                if(predicates.size()==0){
                    return null;
                }else{
                    return cb.and(predicates.toArray(new Predicate[0]));
                }
            }
        };
    }
}

The query is executed with bRepository.findAll(BSpecification.filter(filter)); and I see that after the one to get BEntities based on the date...

select
    b0_.id as id1_7_,
    b0_.some_date as some_date_cr2_7_,
from
    b b0_ 
where
    date(b0_.some_date)>=? 
    and date(b0_.some_date)<=?

... there is another one that gets the one-to-one-lazily-related AEntity:

 select
    a0_.id as id1_9_2_,
    a0_.b_id as b14_9_2_,
from
    a a0_ 
where
    a0_.b_id=?

Due to performance reasons I need to prevent the loading of AEntities, why is this criteria fetching them?

UPDATE: Trying to simplify the problem I have just loaded one of the BEntities bRepository.findOne(bId) and the same happens. So it's not about the criteria but about the mapping. What's wrong with it?

codependent
  • 18,032
  • 17
  • 110
  • 225
  • Possible duplicate of [Making a OneToOne-relation lazy](https://stackoverflow.com/questions/1444227/making-a-onetoone-relation-lazy) – Alan Hay Sep 13 '17 at 13:47

1 Answers1

2

This is what actually worked for me, the accepted referenced answer didn't:

Just had to update my Bentity to implement FieldHandler, nothing more than that needed:

@Entity
@Table(name="B")
public class BEntity implements FieldHandled{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @OneToOne(mappedBy = "b", cascade = CascadeType.ALL, optional = true, 
    fetch = FetchType.LAZY)
    private AEntity a;
    ...

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    protected Date someDate;

    public AEntity getA() {
        if (fieldHandler != null) {
            return (AEntity) fieldHandler.readObject(this, "a", a);
        }
        return notificacion;
    }

    public void setA(AEntity a) {
        if (fieldHandler != null) {
            this.a = (AEntity) fieldHandler.writeObject(this, "a", this.a,
                        a);
            return;
        }
        this.a = a;
    }

}
codependent
  • 18,032
  • 17
  • 110
  • 225