在具有多个数据库+多租户的Hibernate JPA中进行Hbm2dll初始化 [英] Hbm2dll initialization in Hibernate JPA with multiple databases + Multitenancy

查看:150
本文介绍了在具有多个数据库+多租户的Hibernate JPA中进行Hbm2dll初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用LocalContainerEntityManagerFactoryBean使用hbm2dll初始化多个数据库?



我在MultiTenancy中为每个租户使用不同的数据源。
我在ApplicationContext.xml中有一个ID为dataSource的默认数据源,我使用dataSource的属性为每个租户生成一个数据源,但改变了url。我将它们添加到自定义MapDataSourceLookup中。



我尝试使用LocalContainerEntityManagerFactoryBean配置JPA初始化。

 < bean class =org.springframework.orm.jpa.JpaTransactionManager
id =transactionManager> ;
< property name =entityManagerFactoryref =entityManagerFactory/>
< / bean>

< bean
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
id =entityManagerFactory>
< property name =persistenceUnitManagerref =pum/>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =databasePlatformvalue =$ {database.dialect}/>
< / bean>
< / property>
< property name =jpaPropertyMap>
< map>
< entry key =hibernate.multi_tenant_connection_providervalue-ref =multitenancyConnectionProvider/>
< entry key =hibernate.tenant_identifier_resolvervalue-ref =tenantResolver/>
< / map>
< / property>
< / bean>

< bean id =pumclass =org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager>
< property name =dataSourceLookupref =dataSourceLookup/>
< property name =persistenceXmlLocations>
< list>
< value> classpath:META-INF / persistence.xml< / value>
< / list>
< / property>
< / bean>


< bean class =com.jolbox.bonecp.BoneCPDataSourcedestroy-method =close
id =dataSource>
< property name =driverClassvalue =$ {database.driverClassName}/>
< property name =jdbcUrlvalue =$ {database.url}/>
< property name =usernamevalue =$ {database.username}/>
< property name =passwordvalue =$ {database.password}/>
< property name =idleConnectionTestPeriodvalue =$ {database.idleConnectionTestPeriod}/>
< property name =idleMaxAgevalue =$ {database.idleMaxAge}/>
< property name =maxConnectionsPerPartitionvalue =$ {database.maxConnectionsPerPartition}/>
< property name =minConnectionsPerPartitionvalue =$ {database.minConnectionsPerPartition}/>
< property name =partitionCountvalue =$ {database.partitionCount}/>
< property name =acquireIncrementvalue =$ {database.acquireIncrement}/>
< property name =statementsCacheSizevalue =$ {database.statementsCacheSize}/>
< property name =releaseHelperThreadsvalue =$ {database.releaseHelperThreads}/>
< / bean>

我有一个自定义的@component dataSourceLookup被注入,它以这种方式创建不同的数据源。

  //使用dataSource中的配置和每个租户的新url添加新数据源
BoneCPDataSource customDataSource = new BoneCPDataSource defaultDataSource.getConfig());
customDataSource.setJdbcUrl(props.getProperty(database.url));
addDataSource(tenantId,customDataSource);
$ b $ logger.info(配置租户:+ tenantId +属性:+ customDataSource.toString());

这是我的persistence.xml:

 <?xml version =1.0encoding =UTF-8standalone =no?> 
< persistence xmlns =http://java.sun.com/xml/ns/persistencexmlns:xsi =http://www.w3.org/2001/XMLSchema-instanceversion = 2.0xsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">
< persistence-unit name =persistenceUnit
transaction-type =RESOURCE_LOCAL>
< provider> org.hibernate.jpa.HibernatePersistenceProvider< / provider>
<属性>
< property name =hibernate.hbm2ddl.autovalue =update/>
< property name =hibernate.ejb.naming_strategyvalue =org.hibernate.cfg.ImprovedNamingStrategy/>
< property name =hibernate.connection.charSetvalue =UTF-8/>
< property name =hibernate.show_sqlvalue =true/>

<! - 多租户属性 - >
< property name =hibernate.multiTenancyvalue =DATABASE/>
< / properties>
< / persistence-unit>



现在唯一的方案是正在创建的是默认数据库。但是指向其他数据库的数据源并没有被创建。由于USER表不存在,我尝试访问用户时产生此错误:



原因:org.hsqldb.HsqlException:用户缺少权限或对象找到:USER

解决方案

我需要使用LocalContainerEntityManagerFactoryBean的自定义扩展类来解决此问题,并实现postProcessEntityManagerFactory(EntityManagerFactory emf,在这种方法中,我循环不同的数据源并在每次迭代中使用该数据源创建entitymanagerfactory,我知道这不是最好的,但如果你知道更好解决方案,我想听:)。 Schemaexport在暂时不支持多宿主中的休眠模式,这是我找到的解决方案。


How do I initialize multiple databases with hbm2dll using LocalContainerEntityManagerFactoryBean?

I am using different datasources per tenant in MultiTenancy. I have a default datasource with id "dataSource" in ApplicationContext.xml and I generate a datasource per tenant using the properties of "dataSource" but changing the url. I add them in a custom MapDataSourceLookup.

I have tried to configure JPA initialization using LocalContainerEntityManagerFactoryBean.

<bean class="org.springframework.orm.jpa.JpaTransactionManager"
    id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    id="entityManagerFactory" >
    <property name="persistenceUnitManager" ref="pum"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="${database.dialect}" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.multi_tenant_connection_provider" value-ref="multitenancyConnectionProvider"/>
            <entry key="hibernate.tenant_identifier_resolver" value-ref="tenantResolver"/>                                              
        </map>
    </property>
</bean>

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    <property name="dataSourceLookup" ref="dataSourceLookup"/>
    <property name="persistenceXmlLocations">
        <list>
            <value>classpath:META-INF/persistence.xml</value>
        </list>
    </property>
</bean>


<bean class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"
    id="dataSource">
    <property name="driverClass" value="${database.driverClassName}" />
    <property name="jdbcUrl" value="${database.url}" />
    <property name="username" value="${database.username}" />
    <property name="password" value="${database.password}" />
    <property name="idleConnectionTestPeriod" value="${database.idleConnectionTestPeriod}" />
    <property name="idleMaxAge" value="${database.idleMaxAge}" />
    <property name="maxConnectionsPerPartition" value="${database.maxConnectionsPerPartition}" />
    <property name="minConnectionsPerPartition" value="${database.minConnectionsPerPartition}" />
    <property name="partitionCount" value="${database.partitionCount}" />
    <property name="acquireIncrement" value="${database.acquireIncrement}" />
    <property name="statementsCacheSize" value="${database.statementsCacheSize}" />
    <property name="releaseHelperThreads" value="${database.releaseHelperThreads}" />
</bean>

I have a custom @component dataSourceLookup that is injected, and it's creating the different datasources in this way.

        //Add new datasource with configuration from "dataSource" and new url per tenant
        BoneCPDataSource customDataSource = new BoneCPDataSource(defaultDataSource.getConfig());
        customDataSource.setJdbcUrl(props.getProperty("database.url"));
        addDataSource(tenantId, customDataSource);

        logger.info("Configuring tenant: " + tenantId + " Properties: " + customDataSource.toString());

This is my persistence.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit"
    transaction-type="RESOURCE_LOCAL">      
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>     
    <properties>            
        <property name="hibernate.hbm2ddl.auto" value="update" />
        <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
        <property name="hibernate.connection.charSet" value="UTF-8" />
        <property name="hibernate.show_sql" value="true" />         

        <!--  Multi-tenancy properties -->
        <property name="hibernate.multiTenancy" value="DATABASE" />
    </properties>
</persistence-unit>

Right now the only scheme that is being created is the default database. But the datasources which point to other databases are not being created. That produce this error when I try to access to an user since USER table doesn't exist:

Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: USER

解决方案

I got to solve it by using an custom extended class of LocalContainerEntityManagerFactoryBean and implementing the method postProcessEntityManagerFactory(EntityManagerFactory emf, PersistenceUnitInfo pui).

In that method, I loop different datasources and create entitymanagerfactory using that datasource in each iteration, I know it is not the best but if you knew a better solution, I would like to listen :). Schemaexport is not supported by hibernate in multitenancy at the moment and this is the solution that I found.

这篇关于在具有多个数据库+多租户的Hibernate JPA中进行Hbm2dll初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆