truy vấn đã chỉ định tìm nạp kết hợp, nhưng chủ sở hữu của liên kết được tìm nạp không có mặt trong danh sách chọn


82

Tôi đang chọn hai cột id nhưng nhận được lỗi được chỉ định:

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=r,role=null,tableName=REVISIONS,tableAlias=revision1_,origin=ENTITY_CHANGED_IN_REVISION entitychan0_,columns={entitychan0_.REV_ID ,className=ru.csbi.registry.domain.envers.Revision}}] [ select ec.id as entityChangeId, r.id as revisionId from ru.csbi.registry.domain.envers.EntityChange as ec  inner join fetch ec.revision as r  where ec.groupEntityId = :groupEntityId and ec.groupName = :groupName  and r.timestamp < :entityDateFrom  and r.timestamp > :entityDateTo  and (        ec.revisionType in (0, 5, 1, 4, 2 )       and not ( ec.otherGroupEntityModified = false and ec.thisGroupEntityModified = true and ec.rowDataModified = false and ec.collectionOfNotGroupEntityModified = false   )      )  group by ec.id, r.id  having count(*) > :start order by r.id desc]

Một số mã:

String hql = " select ec.id as entityChangeId, r.id as revisionId from EntityChange as ec " +
            " inner join fetch ec.revision as r " +
            " where ec.groupEntityId = :groupEntityId" +
            " and ec.groupName = :groupName " +
            " and r.timestamp < :entityDateFrom " +
            " and r.timestamp > :entityDateTo " +
            " and ( " +
            "       ec.revisionType in (" + 
                        RevisionType.ADD.getRepresentation() + ", " + 
                        RevisionType.ONLY_DATA_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.BOTH_COLLECTION_AND_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.ONLY_COLLECTION_PROPERTY_MOD.getRepresentation() + ", " +
                        RevisionType.DEL.getRepresentation() +
                    " ) " +
            "     and not ( "+
                    "ec.otherGroupEntityModified = false and " +
                    "ec.thisGroupEntityModified = true and " +
                    "ec.rowDataModified = false and " +
                    "ec.collectionOfNotGroupEntityModified = false " +
                "  ) " +
            "     ) " +
            " group by ec.id, r.id " +
            " having count(*) > :start" +
            " order by r.id desc";

Cách sửa lỗi và tôi đang làm gì sai?


6
đối với những người tìm kiếm câu hỏi này trong tương lai, trong tình huống của tôi, tôi đã tham gia thuộc tính không lười biếng. Khi tôi loại bỏ điều khoản tham gia, nó đã được giải quyết.
merveotesi

2
Tôi nghĩ rằng trong trường hợp của bạn, vấn đề là bạn không chọn toàn bộ thực thể (EntityChange) mà chỉ chọn một vài cột. Mệnh đề tìm nạp chỉ có ý nghĩa, nếu thực thể gốc được chọn và bạn muốn lấp đầy tập hợp / đối tượng được ánh xạ bằng cách nối nó.
andy

Câu trả lời:


116

Sử dụng thường xuyên join thay vì join fetch(nhân tiện, nó innertheo mặc định):

String hql = " select ec.id as entityChangeId, r.id as revisionId from EntityChange as ec " + 
        " join ec.revision as r " + ...

Như thông báo lỗi cho bạn biết, join fetchkhông có ý nghĩa ở đây, vì đó là một gợi ý về hiệu suất buộc tải bộ sưu tập một cách háo hức.


4
Chỉ để làm rõ, join fetchcũng có thể được sử dụng để buộc tải một cách háo hức một liên kết chẳng hạn như trường được chú thích bằng @ManyToOne chứ không chỉ các bộ sưu tập.
Robert Hunt

49
Hm .. Tôi đang gặp sự cố tương tự, nhưng tôi cần thực hiện tìm nạp tham gia để tránh n + 1 sự cố
Zhenya

4
@levgen, tôi không biết chi tiết về truy vấn của bạn, nhưng xin lưu ý rằng truy vấn đếm không được có "tìm nạp". codingexplained.com/coding/java/spring-framework/...
mỉm cười

3
@levgen Thật khó để giúp bạn mà không nhìn thấy mã, nhưng nếu xảy ra trường hợp bạn sử dụng Dữ liệu mùa xuân với @Querychú thích, thì bạn có thể chỉ định các truy vấn riêng biệt để tìm nạp và đếm: hãy xem câu hỏi này (Spring-Data FETCH JOIN with Paging không hoạt động) để biết chi tiết.
naXa

2
Xóa "tìm nạp" đã dẫn tôi đến sự cố N + 1 và khiến mọi thứ trong ứng dụng của tôi bị treo. Không muốn giới thiệu giải pháp này cho bất kỳ ai.
Alkis Mavridis

18

Khi bạn cần tìm nạp tham gia, việc xóa tìm nạp sẽ không đáp ứng được nhu cầu của bạn.

Thay vào đó, điều bạn nên làm là chỉ định một truy vấn đếm cùng với nó.

Giả sử bạn đang phân trang kết quả, bên dưới là truy vấn jpa lấy id làm tham số và sẽ gây ra sự cố bạn đã chỉ định và truy vấn thứ hai giải quyết vấn đề này bằng cách thêm truy vấn đếm vào nó.

Lưu ý: fk_fieldlà thuộc tính trong tableA có rln một-nhiều. Truy vấn đếm không sử dụng tìm nạp kết hợp.

@Query(value = "from TableA a LEFT JOIN FETCH a.fk_field where a.id = :id") 

@Query(value = "from TableA a LEFT JOIN FETCH a.fk_field where a.id = :id", 
  countQuery = " select  count(a) from TableA a left join a.fk_field where a.id = :id")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.