事务中的 Spring Boot LazyInitializationException

Posted

技术标签:

【中文标题】事务中的 Spring Boot LazyInitializationException【英文标题】:Spring Boot LazyInitializationException inside Transaction 【发布时间】:2019-12-09 00:33:24 【问题描述】:

我在 Spring Boot 中有一个服务层类。这个类可以获取我的模型。我正在将所有模型对象转换为响应对象 (DTO)。问题是我在事务中得到了一个 LazyLoadException。在我看来,这不应该发生,因为数据库连接仍然是打开的。或者这是错的?提前致谢!

@Cacheable
@Transactional(propagation = Propagation.REQUIRED)
public List<DatabaseServerResponse> getDatabaseServers(Pageable pageable)
    System.err.println(TransactionSynchronizationManager.isActualTransactionActive());
    List<DatabaseServerResponse> databaseServerResponses= databaseServerRepository
            .findAll(pageable)
            .get()
            .map(databaseServer -> databaseServerConverter.convertToDatabaseServerResponse(databaseServer))
            .collect(Collectors.toList());
    System.err.println(TransactionSynchronizationManager.isActualTransactionActive());
    return databaseServerResponses;

原因:org.hibernate.LazyInitializationException:不能 初始化代理 [com.sportradar.promt.domain.promt.Environment#1] - 没有会议 org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169) 在 org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309) 在 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45) 在 org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) 在 com.sportradar.promt.domain.promt.Environment$HibernateProxy$ZNab0Ju2.getName(未知 源) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native 方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688) 在 com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ...省略了109个常用框架

@Entity
@Table(name = "databaseservers")
@Getter
@Setter
public class DatabaseServer 

@Id
private Integer id;

@Column(name = "name")
private String name;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "environment_id", referencedColumnName = "id", columnDefinition = "TINYINT(3)")
private Environment environment;

@Column(name = "host")
private String host;

@Column(name = "dbuser")
private String dbUser;

@Column(name = "dbpasswd")
private String dbPassword;



打开视图设置已被禁用。

  jpa:
    open-in-view: false

【问题讨论】:

您在事务之外得到了异常... Jackson 参与其中,因此它试图将对象序列化为 JSON 并遇到延迟加载的列表或对象。因此错误,启用open-in-view 将“修复”这个问题。或者将其配置为忽略该属性,或者正确初始化对象。 尝试摆脱 lambda map(databaseServer -&gt; databaseServerConverter.convertToDatabaseServerResponse(databaseServer)) 并在通常的 for 循环中转换为 DTO。 @M.Deinum open-in-view 是反模式。在this blog.中演示 这就是我写“修复”的原因... 【参考方案1】:

好的,我找到了解决方案,Environment.class 被注入到 DTO 中,这根本不起作用。我只是忘了将 Environment.class 映射到 EnvironmentResponse.class

【讨论】:

以上是关于事务中的 Spring Boot LazyInitializationException的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 测试中的事务未回滚

spring boot中的@Transactionnal注解真的会创建事务吗?

企业分布式微服务云SpringCloud SpringBoot mybatis (十七)Spring Boot中的事务管理

Spring Boot - 事务管理不起作用

spring-boot里配置事务管理

Spring Boot事务配置管理