java - JPA LazyInitialisationException - 无法初始化代理
问题描述
是的,我见过类似的问题,但没有一个答案真正让我找到了解决方案。我没有在任何地方使用线程,并且相同的代码在另一个 jhipster 应用程序中工作,所以我很难过为什么这个提升+移位会导致休眠问题。
public UserDetailsContextMapper userDetailsContextMapper() {
return new UserDetailsContextMapper() {
@Override
public UserDetails mapUserFromContext(
DirContextOperations ctx, String username,
Collection<? extends GrantedAuthority> authorities) {
log.error("2 " + username + " -> " + ctx.toString());
String lowercaseLogonName = username.toLowerCase();
Optional<User> userFromDatabase = userRepository.findOneByLogin(lowercaseLogonName);
if (!userFromDatabase.isPresent()) {
User ldapUser = new User();
ldapUser.setLogin(lowercaseLogonName);
ldapUser.setPassword(RandomStringUtils.random(60)); // We use LDAP password, but the password need to be set
ldapUser.setActivated(true);
try {
Attribute attribute = ctx.getAttributes().get("mail");
ldapUser.setEmail( attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
attribute = ctx.getAttributes().get("givenname");
ldapUser.setFirstName(attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
attribute = ctx.getAttributes().get("sn");
ldapUser.setLastName(attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
} catch (NamingException e) {
log.warn("Couldn't get LDAP details for user: " + lowercaseLogonName);
}
Set<Authority> newUserAuthorities = new HashSet<>();
Authority authority = authorityRepository.getOne(AuthoritiesConstants.USER);
newUserAuthorities.add(authority); <-- This line in the Exception
ldapUser.setAuthorities(newUserAuthorities);
ldapUser.setLangKey("en");
userRepository.saveAndFlush(ldapUser);
}
例外:
org.hibernate.LazyInitializationException: could not initialize proxy [com.app.my.let.domain.Authority#ROLE_USER] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:155)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
at com.app.my.let.domain.Authority_$$_jvst758_1e.hashCode(Authority_$$_jvst758_1e.java)
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at java.util.HashSet.add(HashSet.java:220)
at com.app.my.let.config.SecurityConfiguration$1.mapUserFromContext(SecurityConfiguration.java:249) <-- code line above
JPA 属性:
jpa:
database-platform: org.hibernate.dialect.SQLServer2012Dialect
database: SQL_SERVER
show_sql: true
format_sql: true
properties:
hibernate.id.new_generator_mappings: true
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
编辑 - 这解决了我的问题:
Optional<Authority> optAuthority = authorityRepository.findById(AuthoritiesConstants.USER);
Authority authority = optAuthority.get();
解决方案
这一行:
Authority authority = authorityRepository.getOne(AuthoritiesConstants.USER);
只为您提供对实体的引用。它在后台调用EntityManager#getReference
. 正如所说,这不是实体,只是对象关系映射目的的引用。抛出异常,因为您试图将其转换到事务环境之外。
有几个解决方案。要获取实体,您必须EntityManager#find
在事务中使用或执行它(使用@Transactional
方法)。在这里,您还可以调用Hibernate.initialize(authority)
以从数据库中获取实体。
推荐阅读
- php - 当另一个 AJAX 函数成功时,我可以自动运行一个 AJAX 函数吗?
- groovy - Jmeter:如何通过代码禁用监听器(groovy)
- php - 如何在不安装在 Windows 10 上的情况下知道与特定 XAMPP 版本关联的 php 版本?
- django - 有没有办法让 Django DateField 中的 date_from 和 date_to 中的年份保持不变,并计算这两个字段的天数
- c - 如何对取决于其他数量的数组进行排序?
- mongodb - 无法使用 Kafka-Spark 结构化流向 MongoDB 发送数据
- c - 将动态分配的内存释放给我正确创建的结构
- wordpress - 如何在自定义登录页面上检查 wp_user 表中的用户?
- javascript - 如何将 Mocha 与 Create-React-App 和 Typescript 一起使用?获取 SyntaxError:意外的令牌导入
- ionic-framework - 在离子打字稿中订阅和取消订阅 Observable