2017-10-16 32 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