我正在开发一个变异项目,它为每个租户维护不同的架构,遵循项目
由于我们动态切换租户,所以看起来好像遗漏了一些配置,即“关闭会话或不保持会话打开以获取 LAZY 加载的对象”。这会导致“无法初始化代理 - 无会话”错误。 请检查下面的链接以访问完整的项目和数据库模式脚本,请按照自述文件中给出的步骤操作。
项目我尝试将服务方法放入@Transactional注释中,但这不起作用。
我期望它再次调用延迟加载的对象,这个项目是复杂项目的简化版本,实际上我有更多的延迟加载对象。
问题:- 我没有收到会话错误“无法初始化代理 [com.amran.dynamic.multitenant.tenant.entity.Tenant#1] - 无会话” 在第 26 行(/dynamicmultitenant/src/main/java/com/amran/dynamic/multitenant/tenant/service/ProductServiceImpl.java)
TenantDatabaseConfig
和
MasterDatabaseConfig
中,您已正确添加 @EnableTransactionManagement
,它将根据请求设置交易。但是 - 具有(隐式) @Transactional
注释的最外层组件是
ProductRepository
(由于它是由 SimpleJpaRepository
类实现的 - 该类已应用注释 - https://github.com/studygolang/growth/ com/spring-projects/spring-data-jpa/blob/864c7c454dac61eb602674c4123d84e63f23d766/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java#L95) 因此您的
productRepository.findAll();
调用将启动一个事务,创建一个JPA会话,运行查询,关闭会话,关闭事务,这意味着不再有任何打开的事务/会话来执行延迟加载.
因此,你最初的尝试我尝试将服务方法放入@Transactional注释中,但这不起作用。
这是
正确的做法。 您没有准确地说出您尝试做什么以及在哪里,但有一些事情可能会出错。首先,确保您添加的是
org.springframework.transaction.annotation.Transactional
而不是 javax.transaction.Transactional
注释。
which事务管理器来配置注释,否则它可能会使用针对主数据库连接创建的现有/新事务,不是租客。
在这种情况下,我认为:
@Service
@Transactional(transactionManager = "tenantTransactionManager")
public class ProductServiceImpl implements ProductService {
应该适合您,并使服务的所有方法都绑定到租户数据库连接上的事务。
回答后续问题:
您能否建议一种更好的方法在我的所有服务类中注入我的tenantTransactionManager,因为我不想在所有服务类中提及tenantTxnManger(如果有更好的方法的话)?
是的,当然。您可以创建一个应用多个其他注释的元注释,这样您就可以创建:
/** * Marks class as being a service operating on a single Tenant */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Service @Transactional("tenantTransactionManager") public @interface TenantService { }
然后您可以简单地用
@TenantService
而不是
@Service
来注释您的服务类:
@TenantService
public class ProductServiceImpl implements ProductService {
当在打开的上下文之外访问延迟加载模型时 Hibernate会话则出现此异常。
您可以使用方法级别的@Transactional 注解。就这样吧
public interface ProductService { @Transactional YourDto methodTobeImplemented(Params); } // And implementation service class no need to annotated. @Service public class ProductServiceImpl implements ProductService { @Override YourDto methodTobeImplemented(Params){ return yourDto } }