Tho*_*ler 0 java hibernate spring-data
我正在从以下项目迁移项目:
当我在控制器方法中访问来自我的数据库的对象时,我正在运行"org.hibernate.LazyInitializationException:无法初始化代理 - 无会话".
这是我的代码的精简版:
// CustomUser.java
@Entity
@Access(AccessType.FIELD)
@Table(name = "users")
public class CustomUser implements Serializable {
...
@Id
@GeneratedValue//details omitted
@GenericGenerator//details omitted
@Column(name = "id", insertable = true, updatable = true, unique = true, nullable = false)
private Long id;
@Column(name = "name")
private String name;
public String getName() { return name; }
}
// UserController.java
@RequestMapping(value = "/user/{userId}/", method = RequestMethod.GET)
public String showUser(@PathVariable("userId") CustomUser user) {
System.out.println("user name is [" + user.getName() + "]");
return "someTemplate";
}
// UserService.java
@Service
public class UserServiceImpl implements UserService {
@Autowired UserRepository userRepository;
@Override
public User findUserById(Long userId) {
return userRepository.getOne(userId);
}
}
// UserRepository.java
public interface UserRepository extends JpaRepository<CustomUser, Long> { }
// UserConverter.java
@Component
public class UserConverter implements Converter<String, CustomUser> {
@Autowired UserService userService;
@Override
public CustomUser convert(String userId) {
CustomUser user = userService.findUserById(SomeUtilClass.parseLong(userId));
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个@Configuration WebMvcConfigurerAdapter类,它自动装配UserConverter实例并将其添加到FormatterRegistry.
在开始此升级之前,我可以点击: http:// server:port/user/123 /
并且Spring将采用"123"字符串,UserConverter :: convert方法将触发并点击Postgres数据库以查找具有该id的用户,并且我将在控制器的"showUser"方法中找回CustomUser对象.
但是,现在我得到了org.hibernate.LazyInitializationException.甚至只是"的println(用户)",而无需访问现场 - 当我试图在"showUser"的方法来打印出用户的名字出现这种情况的.
我从搜索中得到的大部分信息都表明,这个异常来自于一个对象有一个延迟加载的子对象集合(比如我的CustomUser有一个Permission对象的集合或映射到不同数据库的东西)表).但在这种情况下,我甚至没有这样做,这只是对象上的一个字段.
我最好的猜测是,这是因为某种类型的休眠会话在转换器完成其工作后被终止,所以然后回到控制器中我没有有效的会话.(虽然我再也不知道为什么CustomUser对象回来不可用,我不是要尝试获取子集合).
我已经添加了Hibernate的注解"@Proxy(懒惰=假)"我CustomUser.java,如果我这样做,问题消失.但是,我不知道这是一个很好的解决方案 - 由于性能原因,我真的不觉得我要下去的热切地获取一切的道路.
我也尝试用@Transactional注释各种事物(服务方法,控制器方法等); 我没有得到这个工作,但我仍然相当新的春天,我可能会在错误的地方尝试或误解应该做什么.
在我的所有Entity类中,有没有更好的方法来处理这个问题而不仅仅是"@Proxy(lazy = false)"?
当前的问题来自于使用userRepository.getOne(userId).它在SimpleJpaRepository使用中实现EntityManager.getReference.此方法仅返回一个仅包含其ID的代理.只有当一个属性被访问时,才会延迟加载.这包括像name您的情况一样的简单属性.
立即修复是使用findOne哪个应该加载实体的所有应该包含简单属性的渴望属性,因此异常消失.
请注意,这会稍微改变转换器的行为.当数据库中不存在id时,当前版本不会失败,因为它永远不会检查.新的将获得一个空的Optional,你必须将它转换为null或抛出异常.
但是存在(或可能存在)更大的隐藏问题:实体仍然是分离的,因为在没有显式事务划分的情况下,事务只跨越单个存储库调用.因此,如果您以后想要访问延迟加载的属性,则可能会再次遇到相同的问题.我看到了各种选择:
保持原样,意识到您不能访问延迟加载的属性.
确保在调用转换器之前启动事务.
在控制器中标记控制器@Transactional并将用户(再次)加载到控制器中.
| 归档时间: |
|
| 查看次数: |
2332 次 |
| 最近记录: |