Spring Data,JPA @ManyToOne懒惰初始化无法正常工作

Ins*_*sFi 7 java spring hibernate jpa spring-data-jpa

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

我在Aim和User之间有@ManyToOne关系.

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

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

分别.

@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;
}
Run Code Online (Sandbox Code Playgroud)

@OneToMany协会与懒惰提取工作正常.方法不嵌套到另一个@Transactional方法,所以@Transactional工作正常.

在此输入图像描述

在此输入图像描述

所以记录存在.

  1. UserAim不是final和实现 Serializable
  2. 一些消息来源建议将注释放在getter上.它也行不通.
  3. @Fetch(FetchMode.SELECT)同样的情况=
  4. 通过Hibernate查询结果相同,但是使用左连接提取的 HQL查询工作正常
  5. 我的FK 在INSERT CASCADE上ON UPDATE CASCADE
  6. optional = false也试过......

注意我没有LazyInitException



提前致谢!

Dun*_*ear 3

我从您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
}
Run Code Online (Sandbox Code Playgroud)

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

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

这还有一个额外的好处,您可以调试事物是如何延迟加载的。

顺便说一句,我们发现让查找例程在找不到某些内容时抛出异常是一个坏主意。这是因为您可能想要使用查找例程来查找实体是否不存在。如果这种情况发生在事务中,您的异常可能会触发不需要的回滚(除非您专门忽略它)。最好返回null并检查,而不是使用try ... catch.