2017-10-16 39 views
1

所以我有以下映射的Comment實體;如何在訪問唯一標識符時防止延遲初始化?

@Data 
@ToString(exclude = {"user", "place"}) 
@Entity 
public class Comment extends AbstractEntity { 

    @ManyToOne 
    private User user; 

    @ManyToOne 
    private Place place; 

    @Column(columnDefinition = "TEXT") 
    private String comment; 

    @Column 
    private Integer rating; 

    @Column 
    private Boolean approved; 
} 

我取Comments這樣

Page<Comment> comments = commentRepository.findByApprovedIsFalseOrApprovedIsNull(pageable); 

,並把它變成視圖表這樣

    <tr th:each="comment,i : ${comments}"> 
         <td><input name="places" th:value="${comment.id}" type="checkbox"></td> 
         <td th:text="${comments.number} * ${comments.size} + ${i.count}">LP1</td> 
         <td th:text="${comment.user.id}">1234</td> 
         <td th:text="${comment.place.id}">5432</td> 
         <td th:text="${comment.createdAt}">2014-04-10</td> 
         <td th:text="${comment.comment}">Lorem ipsum and more</td> 
         <td>Location</td> 
        </tr> 

現在的問題是,儘管Comment表(是的,沒有實體)包含列user_idplace_id,執行額外的選擇以獲取不同的PlaceUser關係。由於我只訪問這些實體的標識符,實際上它們已經隱藏在Comment的隱藏之下,爲什麼會發生這種初始化?是否可以省略這些額外的初始化提取?

編輯:

我已經檢查了一些消息來源,我也發現了,那BasicLazyInitializer必須返回標識僅就像我需要的能力,但我不知道,什麼樣的條件必須在頂層得到滿足得到這個分支appied。看看這裏: enter image description here

+0

您是否嘗試添加提取和可選屬性,即'@ManyToOne(fetch = FetchType.LAZY,optional = false)'? –

+0

@MadhusudanaReddySunnapu,但默認情況下它們是懶惰的,整個問題表明關係得到了懶惰初始化,這正是我想避免的(因爲它只是因爲id獲取而剩餘) – Antoniossss

+0

您可以按照以下建議映射其他字段或指定連接在您的查詢中進行提取,該查詢應該加載1次中的所有數據並防止用戶和地點的其他查詢。 –

回答

2

好了,我有我需要的解決方案。它不需要額外的JPQL,也不需要像pirho這樣的本地查詢,也不需要模糊解決方法,如72服務建議。

所有我們所要做的就是把@Access(AccessType.PROPERTY)private Long id;場和定義默認@Access(AccessType.Field)房產的休息。如果您已通過@Access註釋使用屬性訪問,或者使用ORM註釋獲取器而不是字段進行註釋,則不需要這些內容。

@Data 
@MappedSuperclass 
@Access(AccessType.FIELD) 
public abstract class AbstractEntity { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(updatable=false,nullable=false) 
    @Access(AccessType.PROPERTY) 
    private Long id; 

這工作就像一個魅力。在訪問關係的ID字段時沒有N + 1查詢。

0

您可以將外鍵映射到單獨的字段爲只讀。

@Column(insertable=false, updatable=false) 
private Integer userId; 

@Column(insertable=false, updatable=false) 
private Integer placeId; 
1

您可以直接映射到一個POJO

public class Response { 

    private Integer userId 

    private Integer placeId 

    private String comment; 

    public Response(Integer userId, Integer placeId, String comment){ 
    ..... 
    } 


} 


@Query("select new Response(c.user.id, c.place.id, c.comment) from Comment c where ....") 
private Resposne myCustomQuery(....) 

看看https://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch11.html#ql-expressions 11.5

+0

這個 - 如果按照想要的方式工作 - 將是正確的方式,那麼與模型分離,IMHO – pirho

+0

這甚至不是我想要的。這並不意味着你必須包含另一個瞬態實體,除非它是一個投影,View應該採用一個模型並渲染它,這就是分離的意思,而不是關於沒有模型知識的觀點 – Antoniossss

+0

我說過「Kind a」。你提供的是非常好的,適用於你的問題,但是如果你隨時需要任何屬性,不僅僅是id? – pirho