当前位置: 首页 > 面试题库 >

LazyInitializationException尝试获取懒惰的初始化实例

姚航
2023-03-14
问题内容

当我尝试获取懒惰的初始化实体时,我在IDE中看到以下异常消息(我无法找到它在代理实体中的存储位置,因此无法为该异常提供整个堆栈跟踪):

Method threw 'org.hibernate.LazyInitializationException' exception. Cannot evaluate com.epam.spring.core.domain.UserAccount_$$_jvste6b_4.toString()

这是我尝试访问要使用的惰性初始化实体的字段后得到的堆栈跟踪:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)

    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)

    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)

    at com.epam.spring.core.domain.UserAccount_$$_jvstfc9_4.getMoney(UserAccount_$$_jvstfc9_4.java)

    at com.epam.spring.core.web.rest.controller.BookingController.refill(BookingController.java:128)

我正在使用Spring
Data,已配置JpaTransactionManager,数据库是MySql,ORM提供程序是Hibernate4。注释@EnableTransactionManagement处于启用状态,@
Transactional随处可见,但无济于事。

这是一个关系:

@Entity
public class User extends DomainObject implements Serializable {

    ..

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_fk")
    private UserAccount userAccount;

    ..

@Entity
public class UserAccount extends DomainObject {

    ..

    @OneToOne(mappedBy = "userAccount")
    private User user;

    ..

..一个配置:

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getRequiredProperty(PROP_NAME_DATABASE_DRIVER));
        dataSource.setUrl(env.getRequiredProperty(PROP_NAME_DATABASE_URL));
        dataSource.setUsername(env.getRequiredProperty(PROP_NAME_DATABASE_USERNAME));
        dataSource.setPassword(env.getRequiredProperty(PROP_NAME_DATABASE_PASSWORD));
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROP_ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setJpaProperties(getHibernateProperties());            
        return entityManagerFactoryBean;
     }

    @Bean
    public JpaTransactionManager transactionManager(@Autowired DataSource dataSource,
                                                    @Autowired EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
        jpaTransactionManager.setDataSource(dataSource);

        return jpaTransactionManager;
    }

..这就是我想要检索UserAccount的方式:

    @RequestMapping(...)
    @Transactional()
    public void refill(@RequestParam Long userId, @RequestParam Long amount) {
        User user = userService.getById(userId);
        UserAccount userAccount = user.getUserAccount();
        userAccount.setMoney(userAccount.getMoney() + amount);
    }

Hibernate版本是4.3.8.Final,Spring Data 1.3.4.RELEASE和MySql连接器5.1.29。

请问我是否还需要其他东西。先感谢您!


问题答案:

首先,您应该了解问题的根源不是交易。我们有一个事务和一个持久的上下文(会话)。使用@Transactional注释,Spring创建一个事务并打开持久上下文。调用方法后,持久上下文将关闭。

当你调用一个user.getUserAccount()你有一个代理类,包装UserAccount(如果你不加载UserAccountUser)。因此,当关闭持久性上下文时,您可以LazyInitializationException调用的任何方法UserAccount,例如toString()

@Transactional``userService在您的情况下,只能在级别上工作。要开始@Transactional工作,仅将@Transactional注释放在方法上是不够的。您需要使用的方法获取类的对象Spring Context。因此,要更新货币,您可以使用其他服务方法,例如updateMoney(userId, amount)

如果要@Transactional在controller方法上使用,则需要从中获取控制器Spring Context。Spring应该理解,它应该@Transactional用特殊方法包装每个方法,以打开和关闭持久性上下文。其他方法是使用“每个请求的会话数”反模式。您将需要添加特殊的HTTP过滤器

https://vladmihalcea.com/the-open-session-in-view-anti-
pattern/



 类似资料:
  • 问题内容: 创建单例的模式似乎是这样的: 但是我的问题是,如果Singleton构造函数执行的不是单元测试友好的操作,例如如何调用外部服务,jndi查找等,您如何使用这样的类进行单元化? 我想我可以像这样重构它: 现在的问题是,仅出于单元可测试性,我已强制将getInstance同步,因此仅出于测试方面,它将对实际应用程序产生负面影响。有没有解决的办法,由于Java中双重锁定模式的破坏性,似乎其他

  • 我在想Spring中bean的懒惰初始化。对我来说,这里的“懒惰”是否意味着当一个bean被引用时会被创建并不十分清楚。 我认为Spring中的延迟初始化支持是不同的。我认为这是一个基于“方法调用”的惰性创建。我的意思是,每当对该方法调用任何方法时,都会创建该方法。 我认为这可以通过创建特定bean的代理实例并对任何方法调用进行初始化来轻松解决。 我是否遗漏了一些东西?为什么没有实施?这个概念有什

  • 在某些情况下,我的广播接收器是不需要的,所以需要检查接收器是否为空,但有些如何这个对象不为空,即使不使用它和造成崩溃。

  • 问题内容: 我有一个初始化为的变量: 问题是,在某个时候,我需要重置此变量,以便在更改后可以再次初始化。但是如果我将类设置为可选的话,LLVM在尝试将它设置为时会给我一个错误。如果我只是使用将其重置在代码中的某个位置,它将最终显示为。 有没有一种方法可以使用并允许自己重置? 问题答案: 懒惰是明确的仅一次初始化。您要采用的模型可能只是按需初始化模型: 现在,只要是,它会被初始化并返回。可以通过设置

  • 你知道为什么jackson不能将这个集合映射到json格式吗?

  • 因此,我的目标是将数据传输到Stripe为其API提供的。因此,正常情况下,我转到storyboards并将一个新的vc与类连接起来,这样我就可以从另一个vc转到它并进行数据传输。 在此之前,我只是在推动vc,它工作正常,并且知道我可以实例化它并进行数据传输,但即使当我尝试这样做时,我也会得到一个致命的错误: 这是我在中的代码: 我更改了是因为我读了这篇关于init错误的文章,但现在它在运行之前就