如何在一次请求中查询hibernate6的多个租户?

问题描述 投票:0回答:1

我在Quarkus中使用hibernate6的TenantResolver来进行多租户过滤,当然,在springboot中使用CurrentTenantIdentifierResolver也是同样的问题。我发现TenantResolver在一个请求中只执行一次

背景

自定义租户解析器.java

@PersistenceUnitExtension
@RequestScoped
public class CustomTenantResolver implements TenantResolver {

  @Override
  public String getDefaultTenantId() {
    return TenantUtil.NONE.toString();
  }

  @Override
  public String resolveTenantId() {
    var tenantId = TenantUtil.getTenantId().toString();
    System.out.println("resolve tenantId " + tenantId);
    return tenantId;
  }
}

租户实用程序


public class TenantUtil {

  private static final ThreadLocal<Serializable> tl = new ThreadLocal<>();
  public static final Serializable ROOT = "-1";
  public static final Serializable NONE = "-999";

  public static void clear() {
    tl.remove();
  }

  public static Serializable getTenantId() {
    return tl.get();
  }

  public static void setTenantId(Serializable tenantId) {
    tl.set(tenantId);
  }
}

租户过滤器

@Priority(0)
@Provider
public class TenantFilter implements ContainerRequestFilter, ContainerResponseFilter {
  @Override
  public void filter(ContainerRequestContext requestContext) {
    String tenantId = requestContext.getUriInfo().getQueryParameters().getFirst("tenantId");
    TenantUtil.setTenantId(Objects.requireNonNullElse(tenantId, TenantUtil.NONE));
  }

  @Override
  public void filter(
      ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
    TenantUtil.clear();
  }
}

角色资源

@Path("/role")
public class RoleResource {

  @Inject RoleRepository roleRepository;

  @GET
  @Path("list")
  public List<SysRole> list() {
    return roleRepository.select().fetch();
  }

  @GET
  @Path("test")
  public void test() {
    TenantUtil.setTenantId("123");
    System.out.println(roleRepository.select().fetch());
    TenantUtil.setTenantId("456");
    System.out.println(roleRepository.select().fetch());
  }

}

预计

curl http://127.0.0.1/role/list?tenantId=123

[{"id":"1", "tenantId": "123"}]

curl http://127.0.0.1/role/list?tenantId=456

[{"id":"2", "tenantId": "456"}]

问题

curl http://127.0.0.1/role/test

[{"id":"1", "tenantId": "123"}]
[]

CustomTenantResolver.resolveTenantId
只执行一次

spring-boot hibernate jpa quarkus multi-tenant
1个回答
0
投票

租户是在 EntityManager 创建时确定的,EntityManager 通常绑定到您的事务(或者默认绑定到您的请求,但不要依赖它,事务是您的朋友,Quarkus 中的 Hibernate ORM 在外部是只读的)无论如何,交易)。

所以我认为你必须为每个租户使用不同的交易:

public class RoleResource {

  @Inject RoleRepository roleRepository;

  @GET
  @Path("list")
  @Transactional // You really should use transactions
  public List<SysRole> list() {
    return roleRepository.select().fetch();
  }

  @GET
  @Path("test")
  public void test() {
    QuarkusTransaction.requiringNew().run(() -> {
        TenantUtil.setTenantId("123");
        System.out.println(roleRepository.select().fetch());
    });
    QuarkusTransaction.requiringNew().run(() -> {
        TenantUtil.setTenantId("456");
        System.out.println(roleRepository.select().fetch());
    });
  }

}

请参阅本文档了解如何使用事务,特别是有关

QuarkusTransaction
的部分。或者 您可以使用标准的
UserTransaction
,但在我看来它不太实用。

© www.soinside.com 2019 - 2024. All rights reserved.