【问题标题】:Multitenancy - Hibernate Persistence - Don't change SCHEMA多租户 - 休眠持久性 - 不要更改 SCHEMA
【发布时间】:2022-01-17 22:47:54
【问题描述】:

我在尝试使用 Netbeans 在 JPA 应用程序中实现多租户休眠时遇到问题。问题是de方法getEntityManager(String multitenancyIdentifier)本身没有执行代码,参数的值为null,所以没有改变架构

为了实现多租户,我必须包含这 3 个类:

SchemaMultiTenantProvider.java
SchemaTenantResolver.java
MuiltitenancyResolver.java

您可以在此链接上找到此示例: https://developers.redhat.com/blog/2020/11/12/jakarta-ee-multitenancy-with-jpa-on-wildfly-part-2#

SchemaMultiTenantProvider 中,我们有一行来更改架构:

connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");

SchemaTenantResolver 中,我们有一个 Map 来选择参考将登录到应用程序的用户的架构:

public SchemaTenantResolver(){
    userDatasourceMap = new HashMap();
    userDatasourceMap.put("default", "public");
    userDatasourceMap.put("usuario1", "prueba");
}

MuiltitenancyResolver我们设置了tenantIdentifier,设置在getEntityManager(String multitenancyIdentifier)中:

public void setTenantIdentifier(String tenantIdentifier) {
    this.tenantIdentifier = tenantIdentifier;
}

持久性中我有这个:

< provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

< jta-data-source>jdbc/dspw</jta-data-source>
< exclude-unlisted-classes>false</exclude-unlisted-classes>
< properties>
  < property name="javax.persistence.schema-generation.database.action" value="none"/>
  < property name="hibernate.dialect" value="org.hibernate.dialect.PostgresPlusDialect"/>
  < property name="hibernate.multiTenancy" value="SCHEMA"/>
  < property name="hibernate.tenant_identifier_resolver" value="services.SchemaTenantResolver"/>
  < property name="hibernate.multi_tenant_connection_provider" value="services.SchemaMultiTenantProvider"/>
</ properties>

在我的 AbstractFacade 我有这个:

public abstract class AbstractFacade<T> {

private Class<T> entityClass;

@PersistenceUnit
protected EntityManagerFactory emf;

public AbstractFacade(Class<T> entityClass) {
    this.entityClass = entityClass;
    
} 


public EntityManager getEntityManager(String multitenancyIdentifier){
    
    System.out.println("id getEntityManager: " + multitenancyIdentifier);
    
    final SessionFactoryImplementor sfi = emf.unwrap(SessionFactoryImplementor.class);
    final MuiltitenancyResolver tenantResolver = (MuiltitenancyResolver) sfi.getCurrentTenantIdentifierResolver();
    tenantResolver.setTenantIdentifier(multitenancyIdentifier);
    
    return emf.createEntityManager();
}

在同一个类中,我有这个方法可以找到任何 db 对象:

public T find(Object id, String multitenancyIdentifier) {
    System.out.println("id find: " + multitenancyIdentifier);
    return getEntityManager(multitenancyIdentifier).find(entityClass, id);
}

在 Facades 类之一中(例如)我有这个:

public class UsuarioFacade extends AbstractFacade<Usuario> {

@PersistenceContext(unitName = "SPWPersistence")
private EntityManager em;

@Override
public EntityManager getEntityManager(String multitenancyIdentifier) {
    System.out.println("User Facade: " + multitenancyIdentifier);
    return em;
}

public UsuarioFacade() {
    super(Usuario.class);
}

}

最后我使用 (userFacade) UsuarioFacade 进行查询:

System.out.println("Test User: " + usuarioFacade.find(1,"usuario1").getNombre());

结果如下:

id find: usuario1|#]
User Facade: usuario1|#]
Identificador schema: null|#]
Test User: Juan Perez Caceres|#]

测试用户:Juan Perez Caceres 在公共模式(PostGres DB)中,但我传递了用户:usuario1,对应于模式:prueba(测试)。 它不会改变shema。

我能做什么? O_o

【问题讨论】:

    标签: hibernate multi-tenant


    【解决方案1】:

    我已经解决了这个问题。导致问题的原因是我愚蠢地使用了一个不是我设置的 EntityManager。

    解决办法是,在 AbstractFacade 类中,创建 EntityManager em 对象:

    @PersistenceContext(unitName = "SPWPersistence")
    protected EntityManager em;
    

    然后这样修改getEntityManager()方法:

    public EntityManager getEntityManager(String multitenancyIdentifier){
        
        System.out.println("id getEntityManager: " + multitenancyIdentifier);
        
        final SessionFactoryImplementor sfi = emf.unwrap(SessionFactoryImplementor.class);
        final MuiltitenancyResolver tenantResolver = (MuiltitenancyResolver) sfi.getCurrentTenantIdentifierResolver();
        tenantResolver.setTenantIdentifier(multitenancyIdentifier);
        
        em = emf.createEntityManager();
        
        return em;
    }
    

    最后删除 UsuarioFacade 的 getEntityManager() 方法的实例,因为你不需要它:

    @Stateless
    public class UsuarioFacade extends AbstractFacade<Usuario> {
    
        public UsuarioFacade() {
            super(Usuario.class);
        }
    
    }
    

    完成!现在你可以像往常一样使用你的 Facade:

    System.out.println("Test User: " + usuarioFacade.find(1,"usuario1").getNombre());
    

    结果:

     id find: usuario1|#]
     id getEntityManager: usuario1|#]
     Identificador schema: usuario1|#]
     Test User: Marlboro|#]
    

    它改变了架构!

    快乐的结局:D

    【讨论】:

      猜你喜欢
      • 2015-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 2021-06-19
      相关资源
      最近更新 更多