Динамически создавать SessionFactory в Hibernate

В моем приложении есть несколько баз данных для каждого клиента. Я хочу получить доступ к базе данных в соответствии с клиентом, зарегистрированным в моем приложении.

Для этого есть два варианта:
1) Использование нескольких записей SessionFactory в файле hibernate-config.xml.
2) Дублирование файла hibernate pojo.

Но я хочу создать LocalSessionFactoryBean,SessionFactory,TransactionManager во время выполнения. Итак, как я могу это сделать? Я не хочу делать несколько записей SessionFactory и DataSource в файле hibernate-config.xml.

Я пробовал ниже фрагмент.

@Configuration
@EnableTransactionManagement
public class PersistenceHibernateConfig
{

    private String  driverClassName;

    private String  url;

    String          hibernateDialect;

    boolean         hibernateShowSql;

    @Bean
    public LocalSessionFactoryBean alertsSessionFactoryBean()
    {
        final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(this.restDataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.ezdi.cac.bean.table" });
        sessionFactory.setHibernateProperties(this.hibernateProperties());

        return sessionFactory;
    }

    @Bean
    public DataSource restDataSource()
    {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(this.driverClassName);
        dataSource.setUrl(this.url);
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        return dataSource;
    }

    @Bean
    public HibernateTransactionManager transactionManager()
    {
        final HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(this.alertsSessionFactoryBean().getObject());

        return txManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslationPostProcessor()
    {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Bean
    public PersistenceExceptionTranslator exceptionTranslator()
    {
        return new HibernateExceptionTranslator();
    }

    final Properties hibernateProperties()
    {
        return new Properties()
        {
            {
                this.put("persistence.dialect", PersistenceHibernateConfig.this.hibernateDialect);
                this.put("hibernate.show_sql", PersistenceHibernateConfig.this.hibernateShowSql);
            }
        };

    }

    /**
     * @return the driverClassName
     */
    public String getDriverClassName()
    {
        return driverClassName;
    }

    /**
     * @param driverClassName the driverClassName to set
     */
    public void setDriverClassName(String driverClassName)
    {
        this.driverClassName = driverClassName;
    }

    /**
     * @return the url
     */
    public String getUrl()
    {
        return url;
    }

    /**
     * @param url the url to set
     */
    public void setUrl(String url)
    {
        this.url = url;
    }

    /**
     * @return the hibernateDialect
     */
    public String getHibernateDialect()
    {
        return hibernateDialect;
    }

    /**
     * @param hibernateDialect the hibernateDialect to set
     */
    public void setHibernateDialect(String hibernateDialect)
    {
        this.hibernateDialect = hibernateDialect;
    }

    /**
     * @return the hibernateShowSql
     */
    public boolean isHibernateShowSql()
    {
        return hibernateShowSql;
    }

    /**
     * @param hibernateShowSql the hibernateShowSql to set
     */
    public void setHibernateShowSql(boolean hibernateShowSql)
    {
        this.hibernateShowSql = hibernateShowSql;
    }

}

но всякий раз, когда я получаю SessionFactory через LocalSessionFactoryBean, а также через HibernateTransactionManager, я получаю null. Я не знаю, почему я получил null?


person Charvee Shah    schedule 02.10.2014    source источник


Ответы (2)


У вас должен быть взгляд на Hibernate Multi-Tenancy, который специально создан для этого требования. Начиная с Hibernate 4.x, он доступен, и его рекомендуется использовать вместо использования нескольких SessionFactory. Ознакомьтесь с этим сообщением.

person shazin    schedule 02.10.2014

Все последующее имеет смысл только в веб-приложении, но так как вопрос имеет тег spring-mvc...

Предполагая, что у вас есть способ получить имя базы данных из подключенного имени пользователя и не обращаться к базе данных до тех пор, пока пользователь не войдет в систему и не будет установлен сеанс, вы можете просто поместить все данные в область сеанса.

Просто добавьте аннотацию области к соответствующим bean-компонентам:

@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)

использовать прокси-сервер JDP при условии, что вы связываете bean-компонент через интерфейс (должно быть по крайней мере для DataSource и SessionFactory, а также для диспетчера транзакций, если он обычно используется). Если он ломается из-за того, что вам нужно использовать классы, используйте proxyMode=ScopedProxyMode.TARGET_CLASS.

Таким образом, вы даже можете привязать фабрику сеансов к (одноэлементному компоненту) Dao, и благодаря прокси-серверу с ограниченной областью действия каждый пользователь будет использовать свой собственный.

Деликатной частью является написание метода getUrl(), потому что он должен будет вернуть правильный URL-адрес. Но вы также можете использовать bean-компонент с областью действия сеанса для хранения URL-адреса и сохранения URL-адреса во время входа в систему.

person Serge Ballesta    schedule 02.10.2014