Spring 仅访问标识符时如何防止延迟初始化?
因此,我有以下Spring 仅访问标识符时如何防止延迟初始化?,spring,jpa,spring-data,Spring,Jpa,Spring Data,因此,我有以下Comment实体的映射 @Data @ToString(exclude = {"user", "place"}) @Entity public class Comment extends AbstractEntity { @ManyToOne private User user; @ManyToOne private Place place; @Column(columnDefinition = "TEXT") private
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;
}
我像这样获取注释
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>
Page comments=commentRepository.findbyapprovedisfalse或pprovedisnull(可分页);
把它放在像这样的桌子上
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>
LP1
1234
5432
2014-04-10
Lorem ipsum及更多
位置
现在的问题是,尽管Comment
表(是,不是实体)包含列user\u id
和place\u id
,但执行额外的选择以获取不同的place
和user
关系。由于我只访问那些实体的标识符,它们实际上应该已经隐藏在带有注释的引擎盖下,为什么会发生初始化?是否可以对这些额外的初始化回迁进行ommit
编辑:
我检查了一些源代码,发现BasicLazyInitializer
只能够按照我的要求返回标识符,但我不知道在顶层必须满足哪些条件才能应用此分支。请看这里:
您可以将外键映射到单独的只读字段
@Column(insertable=false, updatable=false)
private Integer userId;
@Column(insertable=false, updatable=false)
private Integer placeId;
您可以直接映射到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(....)
看看
11.5好的,我有一个我需要的解决方案。它不需要额外的JPQL,也不需要像pirho提到的本地查询,也不需要像建议的72个服务那样的模糊处理
我们所要做的就是把@Access(AccessType.PROPERTY)
放在私有长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查询。您是否尝试添加fetch和可选属性,即“@MANYTONE(fetch=FetchType.LAZY,optional=false)”?@MADHUSUDANAREDYSUNNAPU,但默认情况下它们是惰性的,而且整个问题都是关系被惰性初始化,这是我想要避免的(因为它仅因ids fetch而剩余)您可以按照下面的建议映射其他字段,或者在查询中指定一个连接获取,该连接获取应在1go中加载所有数据,并防止对User和Place进行额外查询。@Antoniossss Per JPA,“*ToOne”关系默认情况下是急切的,“*ToMany”默认情况下是惰性的,除非我们重写它们。好的,因此我声明了惰性获取,并且效果仍然相同。调用getId()时,代理将初始化:(如果按照需要工作,这将是正确的方法,将视图与模型分离,IMHOThis-甚至与我想要的不太接近。视图-模型分离并不意味着你必须包含另一个瞬态实体,除非它是投影。视图应该取一个模型并渲染它。这就是这种分离的意义,而不是视图不了解模型。“种类a”我说。您提供的解决方案很棒,可以很好地应用于您的问题。但是,如果您随时需要任何任意属性,而不仅仅是id?@pirho,那么它是一个@列
,获取id是获取“隐藏”的一个特殊用例property.Rest将映射为字段。@Antoniossss我不同意您的看法。视图必须与模型不同,您不能将模型(实体)公开给View/Rest api。您可能会遇到LazyInitializationException等严重问题。例如,当您呈现给视图时:“${comment.user.id}”当您获得任何关联(在渲染阶段)时,您正在从视图中创建一个新查询。因为只有在调用getxxx方法时才会加载该关联。