事务中的 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 -> 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中的@Transactionnal注解真的会创建事务吗?
企业分布式微服务云SpringCloud SpringBoot mybatis (十七)Spring Boot中的事务管理