2014-12-15 22 views
6

Tôi đang cố gắng để thực hiện một EntityGraph với dữ liệu JPA, vì sử dụng QueryDslPredicateExecutor<T> thấy nhiều phương pháp findAll(Predicate, Pageable) người tôi cần, tôi đã cố gắng để ghi đè lên nó để chú thích với @EntityGraph thì những rắc rối bắt đầu nó ném:Overriding mùa xuân-Data-JPA phương pháp mặc định chú thích với EntityGraph gây QueryException

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=appointment,role=com.physioclinic.entity.Appointment.createdBy,tableName=user,tableAlias=user5_,origin=appointment appointmen0_,columns={appointmen0_.createdBy_id ,className=com.physioclinic.entity.User}}] [select count(appointment) 
from com.physioclinic.entity.Appointment appointment where lower(concat(concat(appointment.patient.person.name,?1),appointment.patient.person.surname)) like ?2 escape '!']; nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=appointment,role=com.physioclinic.entity.Appointment.createdBy,tableName=user,tableAlias=user5_,origin=appointment appointmen0_,columns={appointmen0_.createdBy_id ,className=com.physioclinic.entity.User}}] 

Khi tôi sử dụng phương pháp mặc định cách nó nói không có gì xấu xảy ra, thậm chí sử dụng cùng một Predicate, nhưng tôi không thể sử dụng EntityGraph, có một số vấn đề với thực hiện của tôi hay với Predicate?

Làm theo các đối tượng trong kịch bản:

Entity

@Table(name = "appointment") 
@Entity 
@Getter 
@Setter 
@NamedEntityGraphs({@NamedEntityGraph(name = "graph.Appointment.default", includeAllAttributes = true, 
    attributeNodes = {@NamedAttributeNode(value = "physiotherapist"), 
     @NamedAttributeNode(value = "patient"), 
     @NamedAttributeNode(value = "care")})}) 
public class Appointment extends PersistableAuditable<User, Long> { 

    private static final long serialVersionUID = -4325126792470516159L; 

    @DateTimeFormat(pattern = "dd/MM/yyyy") 
    @NotNull 
    @Column(name = "date") 
    private LocalDate date; 

    @DateTimeFormat(pattern = "HH:mm") 
    @NotNull 
    @Column(name = "schedule") 
    private LocalTime schedule; 

    @ManyToOne 
    @JoinColumn(name = "physiotherapist", referencedColumnName = "id") 
    private Physiotherapist physiotherapist; 

    @ManyToOne 
    @JoinColumn(name = "service", referencedColumnName = "id") 
    private Service service; 

    @ManyToOne 
    @JoinColumn(name = "patient", referencedColumnName = "id") 
    private Patient patient; 

    @ManyToOne(cascade = CascadeType.REMOVE) 
    @JoinColumn(name = "care", referencedColumnName = "id") 
    private Care care; 

    public Appointment(long id) { 
     setId(id); 
    } 

    public Appointment() { 
    } 

    /** 
    * Helpers 
    */ 

    public boolean isSpecialPrice() { 
     return care.getPrivateCare() && care.getSpecial() && care.getSpecialPrice() != null; 
    } 

    public boolean isPrivatePrice() { 
     return care.getPrivateCare() && care.getHealthCare() == null; 
    } 

    public boolean isHealthCarePrice() { 
     return !care.getPrivateCare() && care.getHealthCare() != null; 
    } 
} 

Repository

public interface AppointmentRepository extends JpaRepository<Appointment, Long>, 
               QueryDslPredicateExecutor<Appointment> { 

    @EntityGraph(value = "graph.Appointment.default") 
    Page<Appointment> findAll(Predicate predicate, Pageable pageable); 
} 

Predicate

public final class AppointmentPredicate { 

    private AppointmentPredicate() { 
    } 

    public static Predicate bySearch(String search) { 
     QPerson person = QAppointment.appointment.patient.person; 
     return person.name.concat(" ").concat(person.surname).containsIgnoreCase(search); 
    } 

} 
+0

Nơi bạn có thể tìm thấy giải pháp? Có cùng một vấn đề. – bjoernhaeuser

+0

Đáng buồn là tôi không thể tìm thấy giải pháp, vì vậy tôi chỉ để lại nó theo mặc định –

Trả lời

5

tôi đã phải đối mặt với chính xác cùng một vấn đề và có rất nhiều vui vẻ gỡ lỗi mã nguồn mùa xuân. Vì vậy, nguyên nhân gốc rễ là: mùa xuân đang áp dụng các gợi ý về truy vấn đếm dẫn đến lỗi đó.

QueryDslJpaRepository.java:

@Override 
public Page<T> findAll(Predicate predicate, Pageable pageable) { 

    JPQLQuery countQuery = createQuery(predicate); 
    JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate)); 
.... 
} 

protected JPQLQuery createQuery(Predicate... predicate) { 

    JPAQuery query = querydsl.createQuery(path).where(predicate); 
    CrudMethodMetadata metadata = getRepositoryMethodMetadata(); 

    if (metadata == null) { 
     return query; 
    } 

    LockModeType type = metadata.getLockModeType(); 
    query = type == null ? query : query.setLockMode(type); 

    for (Entry<String, Object> hint : getQueryHints().entrySet()) { 
     query.setHint(hint.getKey(), hint.getValue()); 
    } 

    return query; 
} 

Và cách giải quyết là: tạo một giao diện hỗ trợ giao diện kho lưu trữ của bạn và thực hiện nó trọng logic tạo truy vấn. Đây là thực hiện nửa đêm của tôi (nó chỉ là một nguyên mẫu mà phải được cải thiện tất nhiên).

public interface SomeRepository extends JpaRepository<SomeEntity, Long>, QueryDslPredicateExecutor<SomeEntity>, SomeRepositoryCustom { 
} 


public interface SomeRepositoryCustom { 
    Page<SomeEntity> findAll(Predicate predicate, Pageable pageable); 
} 

public class SomeRepositoryImpl extends SimpleJpaRepository<SomeEntity, Long> 
    implements SomeEntityRepositoryCustom 
{ 
    private final EntityManager entityManager; 
    private final EntityPath<SomeEntity> path; 
    private final PathBuilder<SomeEntity> builder; 
    private final Querydsl querydsl; 

    @Autowired 
    public SomeRepositoryImpl(EntityManager entityManager) { 
     super(SomeEntity.class, entityManager); 


     CrudMethodMetadata metadata = getRepositoryMethodMetadata(); 
     this.entityManager = entityManager; 
     this.path = SimpleEntityPathResolver.INSTANCE.createPath(SomeEntity.class); 
     this.builder = new PathBuilder<>(path.getType(), path.getMetadata()); 
     this.querydsl = new Querydsl(entityManager, builder); 
    } 

    @Override 
    public Page<SomeEntity> findAll(Predicate predicate, Pageable pageable) { 
     JPAQuery countQuery = createQuery(predicate); 
     JPAQuery query = (JPAQuery) querydsl.applyPagination(pageable, createQuery(predicate)); 

     query.setHint(EntityGraph.EntityGraphType.LOAD.getKey(), 
      entityManager.getEntityGraph("YOUR GRAPH KEY")); 

     Long total = countQuery.count(); 
     List<SomeEntity> content = total > pageable.getOffset() ? query.list(path) : 
      Collections.<SomeEntity> emptyList(); 

     return new PageImpl<>(content, pageable, total); 
    } 

    private JPAQuery createQuery(Predicate predicate) { 
     return querydsl.createQuery(path).where(predicate); 
    } 

} 

Có vẻ như đó là lỗi và tôi sẽ gửi nó đến jpa jpa mùa xuân.

+0

Cảm ơn bạn rất nhiều vì đã chia sẻ điều này, tôi sẽ xem xét và lưu lại các dự án tiếp theo! –

Các vấn đề liên quan