Spring Data,JPA @ManyToOne延迟初始化无法正常工作

时间:2015-05-26 23:49:42

标签: java spring hibernate jpa spring-data-jpa

我知道有很多关于这个问题的类似问题但对我没什么用。

我在Aim和用户之间有 @ManyToOne 关系。

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false, updatable = false)
private User user;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Collection<Aim> userAims;

分别

@Override
@Transactional(propagation = Propagation.REQUIRED)
@PreAuthorize("isAuthenticated() and principal.user.isEnabled() == true")
public Aim findById(String aimId) throws NumberFormatException, EntityNotFoundException {
    Aim aim = null;
    try {
        aim = aimRepository.findOne(Long.parseLong(aimId));
    } catch (NumberFormatException e) {
        throw new InvalidDataAccessApiUsageException(e.getMessage(), e);
    }
    if (aim == null) throw new EntityNotFoundException("Aim with id: " + aimId + " not found!");
    return aim;
}

@OneToMany 关联适用于延迟抓取。方法不会嵌套到另一个 @Transactional 方法,因此 @Transactional 工作正常。

enter image description here

enter image description here

  

所以记录存在。

  1. 课程用户目标不是最终并实施 的序列化
  2. 有些消息来源建议将注释放在getter上。它也没有 工作
  3. @Fetch(FetchMode.SELECT)相同的情况= \
  4. 通过Hibernate查询结果相同,但HQL查询左连接 提取工作正常
  5. 我的FK INSERT CASCADE ON UPDATE CASCADE
  6. optional = false 也尝试了...
  7.   

    注意我没有 LazyInitException


    提前致谢!

1 个答案:

答案 0 :(得分:2)

我猜测你的findById方法中的代码,以及标题中对“懒惰初始化不起作用”的引用,你想通过它的数字找到Aim对象Id,以及关联的User对象。

为了使用延迟加载来执行此操作,您需要“获取”关联对象,并且(最重要的是)您需要“获取”关联实体的某个字段。

所以try块中的代码应该是:

aim = aimRepository.findOne(Long.parseLong(aimId));
if (aim != null && aim.getUser() != null) {
    aim.getUser().getUserId(); // doesn't need to be assigned to anything
}

或者,如果您有可用的记录器,则可以在调试或跟踪日志消息中使用userId

if (aim != null && aim.getUser() != null) {
    logger.debug("Lazy-loaded User " + aim.getUser().getUserId());
}

这有额外的好处,你可以调试延迟加载的方式。

顺便说一句,我们发现了一个很难的方法,即当一个查找例程找不到某个东西时会抛出异常是一个坏主意。这是因为您可能希望使用查找例程来确定实体是否存在 NOT 。如果在事务中发生这种情况,您的异常可能会触发意外的回滚(除非您明确忽略它)。最好返回null并检查,而不是使用try ... catch