Hibernate的问题';s多租户和Spring

Hibernate的问题';s多租户和Spring,spring,hibernate,spring-mvc,multi-tenant,Spring,Hibernate,Spring Mvc,Multi Tenant,我试图掌握如何使用Hibernate、Spring和MySQL实现多租户。对于第一个游乐场示例,我选择了单独的数据库方法:每个租户都有自己的数据库,名为accodingly。此外,还使用另一个数据库来管理租户。特定于租户的数据库保存一些员工数据。对于第一种方法,我不强制用户进行身份验证 我发现很难获得关于这个主题的全面教程,这就是为什么我现在有点迷茫的原因。当我尝试部署Tomcat时,会收到以下消息: WARN : org.hibernate.engine.jdbc.connections.in

我试图掌握如何使用Hibernate、Spring和MySQL实现多租户。对于第一个游乐场示例,我选择了单独的数据库方法:每个租户都有自己的数据库,名为accodingly。此外,还使用另一个数据库来管理租户。特定于租户的数据库保存一些员工数据。对于第一种方法,我不强制用户进行身份验证

我发现很难获得关于这个主题的全面教程,这就是为什么我现在有点迷茫的原因。当我尝试部署Tomcat时,会收到以下消息:

WARN : org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator - Unable to instantiate specified class [sdb.persistence.TenantResolverImpl]
java.lang.ClassCastException: sdb.persistence.TenantResolverImpl cannot be cast to org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider
    at org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator.initiateService(MultiTenantConnectionProviderInitiator.java:100)
    at org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator.initiateService(MultiTenantConnectionProviderInitiator.java:45)
...
ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'staffSessionFactory' defined in ServletContext resource [/WEB-INF/spring/appServlet/spring-data.xml]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to instantiate specified multi-tenant connection provider [sdb.persistence.TenantResolverImpl]
...
Caused by: org.hibernate.service.spi.ServiceException: Unable to instantiate specified multi-tenant connection provider [sdb.persistence.TenantResolverImpl]
    at org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator.initiateService(MultiTenantConnectionProviderInitiator.java:104)
    at org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator.initiateService(MultiTenantConnectionProviderInitiator.java:45)
这是我的Java类的结构:

xml配置分为三个文件。1. <代码>servlet context.xml:


  • spring data.xml
  • 
    org.hibernate.dialogue.mysql5dialogue
    符合事实的
    sdb.domain.Tenant
    org.hibernate.dialogue.mysql5dialogue
    符合事实的
    平民的
    模式
    sdb.persistence.ConnectionProviderImpl
    sdb.persistence.TenantResolverImpl
    
  • spring mvc.xml
  • 
    /WEB-INF/pages/
    .jsp
    
    现在来看Java类。我的DAO都有一个会话工厂字段:

    @存储库
    公共类TenantDaoImpl实现TenantDao{
    @自动连线
    私人SessionFactory租户SessionFactory;
    ...
    @存储库
    公共类StaffDaoImpl实现StaffDao{
    @自动连线
    私人SessionFactory员工SessionFactory;
    
    控制员:

    @控制器
    公共类家庭控制器{
    @自动连线
    斯塔夫道斯塔夫道;
    @RequestMapping(value=“/{companyName}/{staffId}”,method=RequestMethod.GET)
    公共字符串google(模型模型,@PathVariable字符串companyName,@PathVariable字符串staffName){
    List staff=staffDao.getStaff();
    //是的,我知道这个功能实际上应该驻留在Dao或服务层中
    可选的foundStaff=staff.stream().filter(staff->staff.getNames().equals(staffName)).findFirst();
    if(foundStaff.isPresent()){
    model.addAttribute(“foreName”,foundStaff.get().getForeName());
    model.addAttribute(“姓氏”,foundStaff.get().getNames());
    }
    model.addAttribute(“companyName”,companyName);
    返回“工作人员”;
    }
    }
    
    最后,是与多租户相关的源代码。
    TenantResolverImpl.java

    公共类TenantResolverImpl实现CurrentTenantIdentifierResolver{
    @凌驾
    公共字符串resolveCurrentTenantIdentifier(){
    如果(FacesContext.getCurrentInstance()!=null){
    //我不知道这是否行得通-这行是从其他地方抄来的
    返回FacesContext.getCurrentInstance().getExternalContext().getRequestServerName();
    } 
    返回null;
    }
    //不确定如何使用此方法。。。
    @凌驾
    public boolean validateExistingCurrentSessions(){return true;}
    }
    
    ConnectionProviderImpl.java

    公共类ConnectionProviderImpl实现了MultiTenantConnectionProvider{
    私有地图数据源;
    @自动连线
    租户道租户道;
    @凌驾
    公共连接getAnyConnection()引发SQLException{
    //可能应该返回“dummy”之类的连接
    返回getConnection(“谷歌”);
    }
    @凌驾
    公共连接getConnection(字符串租户标识符)引发SQLException{
    if(tenantDao.containtenantWithName(tenantIdentifier)){
    if(!dataSources.containsKey(租户标识符)){
    ComboPooledDataSource=新ComboPooledDataSource(“示例”);
    试一试{
    setDriverClass(“com.mysql.jdbc.Driver”);
    }捕获(PropertyVetOe异常){
    e、 printStackTrace();
    返回null;
    }
    setJdbcUrl(“jdbc:mysql://localhost:3306/“+租户证明人);
    setUser(“根”);
    dataSource.setPassword(“根”);
    dataSources.put(tenantIdentifier,dataSource);
    } 
    返回dataSources.get(tenantIdentifier.getConnection();
    }
    返回null;
    }
    ...
    }
    

    由于我(但)对技术的肤浅理解,我猜代码中有很多错误/缺点。请随意批评任何值得注意的东西。

    希望你自己能解决它,如果不是的话,这里是我的提示: 更改属性,您应该完成;)

    sdb.persistence.ConnectionProviderImpl
    sdb.persistence.TenantResolverImpl
    
    <prop key="hibernate.tenant_identifier_resolver">sdb.persistence.ConnectionProviderImpl</prop>
    <prop key="hibernate.multi_tenant_connection_provider">sdb.persistence.TenantResolverImpl</prop>