JPA ленивое отношение OneToOne выбирается при загрузке или запросе объекта, когда это не должно? Зачем?

Учитывая эти два объекта с отношением OneToOne (A как сторона-владелец, содержащая идентификатор объекта B):

@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;

}

Я использую запрос критерия, чтобы получить все объекты B в течение данной даты:

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]));
                }
            }
        };
    }
}

Запрос выполняется с bRepository.findAll(BSpecification.filter(filter)); и я вижу, что после того, как получить BEntities на основе даты...

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)<=?

... есть еще один, который получает AEntity, связанный с лениво:

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

Из-за соображений производительности мне нужно предотвратить загрузку AEntities, почему этот критерий выбирает их?

ОБНОВЛЕНИЕ: пытаясь упростить проблему, я только что загрузил один из BEntities bRepository.findOne(bId) и то же самое происходит. Так что дело не в критериях, а в отображении. Что с этим не так?

1 ответ

Решение

Вот что на самом деле работает для меня, принятый ссылочный ответ не:

Просто пришлось обновить мою Bentity для реализации FieldHandler, не более того:

@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;
    }

}
Другие вопросы по тегам