Mandantenfähigkeit mit Spring + Hibernate: "SessionFactory für Mandantenfähigkeit konfiguriert, aber keine Mandanten-ID angegeben"

In einer Spring 3-Anwendung versuche ich, Mandantenfähigkeit über die native Version von Hibernate 4 zu implementierenMultiTenantConnectionProvider undCurrentTenantIdentifierResolver. Ich sehe dasIn Hibernate 4.1.3 ist ein Problem aufgetreten, aber ich lasse 4.1.9 laufen und erhalte immer noch eine ähnliche Ausnahme:

   Caused by:

org.hibernate.HibernateException: SessionFactory configured for multi-tenancy, but no tenant identifier specified
    at org.hibernate.internal.AbstractSessionImpl.<init>(AbstractSessionImpl.java:84)
    at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:239)
    at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1597)
    at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:963)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:328)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:334)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.afflatus.edu.thoth.repository.UserRepository$EnhancerByCGLIB$c844ce96.getAllUsers(<generated>)
    at com.afflatus.edu.thoth.service.UserService.getAllUsers(UserService.java:29)
    at com.afflatus.edu.thoth.HomeController.hello(HomeController.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:746)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:687)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:671)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:448)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1070)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:375)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1004)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:258)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:439)
    at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:246)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:265)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:240)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:589)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:520)
    at java.lang.Thread.run(Thread.java:722) enter code here

Unten ist der relevante Code. In demMultiTenantConnectionProvider Ich habe nur einen blöden Code geschrieben, der jedes Mal eine neue Verbindung zurückgibtCurrentTenantIdentifierResolver Gibt an dieser Stelle immer dieselbe ID zurück. Offensichtlich sollte diese Logik implementiert werden, nachdem ich es geschafft hatte, die Verbindungen zu instanziieren.

config.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
        <list>
            <value>com.afflatus.edu.thoth.entity</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.hbm2ddl">${hibernate.dbm2ddl}</prop>
            <prop key="hibernate.multiTenancy">DATABASE</prop>
            <prop key="hibernate.multi_tenant_connection_provider">com.afflatus.edu.thoth.connection.MultiTenantConnectionProviderImpl</prop>
            <prop key="hibernate.tenant_identifier_resolver">com.afflatus.edu.thoth.context.MultiTenantIdentifierResolverImpl</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="autodetectDataSource" value="false" />
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
MultiTenantConnectionProvider.java
package com.afflatus.edu.thoth.connection;

import java.util.Properties;
import java.util.HashMap;
import java.util.Map;

import org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.hibernate.cfg.*;

public class MultiTenantConnectionProviderImpl extends AbstractMultiTenantConnectionProvider {

    private final Map<String, ConnectionProvider> connectionProviders
        = new HashMap<String, ConnectionProvider>();

    @Override
    protected ConnectionProvider getAnyConnectionProvider() {

        System.out.println("barfoo");
        Properties properties = getConnectionProperties();

        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/test");
        ds.setUsername("root");
        ds.setPassword("");

        InjectedDataSourceConnectionProvider defaultProvider = new InjectedDataSourceConnectionProvider();
        defaultProvider.setDataSource(ds);
        defaultProvider.configure(properties);

        return (ConnectionProvider) defaultProvider;
    }


    @Override
    protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
        System.out.println("foobar");
        Properties properties = getConnectionProperties();

        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/test2");
        ds.setUsername("root");
        ds.setPassword("");

        InjectedDataSourceConnectionProvider defaultProvider = new InjectedDataSourceConnectionProvider();
        defaultProvider.setDataSource(ds);
        defaultProvider.configure(properties);

        return (ConnectionProvider) defaultProvider;
    }

    private Properties getConnectionProperties() {
        Properties properties = new Properties();
        properties.put(AvailableSettings.DIALECT, "org.hibernate.dialect.MySQLDialect");
        properties.put(AvailableSettings.DRIVER, "com.mysql.jdbc.Driver");
        properties.put(AvailableSettings.URL, "jdbc:mysql://127.0.0.1:3306/test");
        properties.put(AvailableSettings.USER, "root");
        properties.put(AvailableSettings.PASS, "");

        return properties;

    }
}
CurrentTenantIdentifierResolver.java
package com.afflatus.edu.thoth.context;

import org.hibernate.context.spi.CurrentTenantIdentifierResolver;

public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {

    public String resolveCurrentTenantIdentifier() {
        return "1";
    }

    public boolean validateExistingCurrentSessions() {
        return true;
    }

}

Kann jemand etwas speziell falsch sehen? Dies löst eine Ausnahme aus, sobald eine Transaktion geöffnet wird. Esscheint wieSessionFactory Die Sitzung wird nicht korrekt geöffnet, oder dieSession ignoriert einfach den Wert, der von der zurückgegeben wirdCurrentTenantIdentifierResolver, von dem ich glaube, dass es das Problem in Hibernate 4.1.3 war; dies sollte gelöst worden sein.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage