В моем приложении для каждого клиента есть несколько баз данных. Я хочу получить доступ к базе данных в соответствии с клиентом, зарегистрированным в моем приложении.
Для этого есть два варианта:
1) Использование нескольких записей SessionFactory в файле hibernate-config.xml.
2) Дублировать файл hoidernate 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.I не знаю, почему я получил null?
У вас должен быть взгляд на Hibernate Multi-Tenancy, специально разработанный для этого требования. С Hibernate 4.x он доступен и рекомендуется использовать вместо использования нескольких SessionFactory
. Пожалуйста, прочитайте этот пост.
Все, что следует, имеет смысл только в веб-приложении, но поскольку вопрос имеет тег spring-mvc...
Предполагая, что у вас есть способ получить имя базы данных из подключенного имени пользователя и не обращаться к базе данных до тех пор, пока пользователь не будет зарегистрирован и не будет установлен сеанс, вы можете просто поместить все содержимое в область сеанса.
Просто добавьте аннотацию к соответствующим компонентам:
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
использовать прокси-сервер JDP при условии, что вы привязываете интерфейс через интерфейс (это должно быть по крайней мере для DataSource и SessionFactory, а также для менеджера транзакций, если используется обычная). Если он ломается, потому что вам нужно использовать классы, используйте proxyMode=ScopedProxyMode.TARGET_CLASS
.
Таким образом, вы даже можете связать фабрику сеансов в (singleton bean) Dao, и благодаря охвату прокси-сервера каждый пользователь будет использовать свой собственный.
Деликатной частью является написать метод getUrl()
, потому что он должен будет вернуть правильный URL-адрес. Но вы также можете использовать компонент, обработанный сеансом, для хранения URL-адреса и сохранения URL-адреса во время входа в систему.