Я пытаюсь изменить спящий аннотацию только с одним источником данных, чтобы иметь столько, сколько сохраняется в базе данных. Для того, чтобы пользователь имеет назначенную связь, и добавить новый тип соединения только с перезагрузкой сервера (избегая .war перекомпиляции)Spring 3.1.3 + Конфигурация спящего режима с аннотациями и с помощью (Dynamic) AbstractRoutingDataSource
сервер загружает первый SecurityHibernateConfiguration без проблем:
@Configuration
@EnableTransactionManagement
public class SecurityHibernateConfiguration {
@Autowired
public Parameters parameters;
@Bean
DataSource datasourcesecurity() {
org.apache.commons.dbcp.BasicDataSource dataSource = new org.apache.commons.dbcp.BasicDataSource();
dataSource.setDriverClassName(parameters.getDriverClassName());
dataSource.setUrl(parameters.getUrlSecurity());
dataSource.setUsername(parameters.getUserNameSecurity());
dataSource.setPassword(parameters.getPasswordSecurity());
return dataSource;
}
@Bean
public SessionFactory securitySessionFactory() throws Exception {
Properties props = new Properties();
props.put("hibernate.dialect", parameters.getHibernateDialect());
props.put("hibernate.format_sql", parameters.getFormatSql());
AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
bean.setAnnotatedClasses(new Class[] {
Login.class,
LoginRol.class,
Aplicacio.class,
Rol.class,
RolObjecte.class,
Objecte.class,
RolObjecteAcl.class,
Acl.class,
Tema.class,
Connexio.class
});
bean.setHibernateProperties(props);
bean.setDataSource(datasourcesecurity());
bean.setSchemaUpdate(false);
bean.afterPropertiesSet();
SessionFactory factory = bean.getObject();
return factory;
}
@Bean
public HibernateTransactionManager securitytransactionManager() throws Exception {
return new HibernateTransactionManager(securitySessionFactory());
}
}
Тогда Я создал маршрутизации DataSource вроде этого:
public class RoutingDataSource extends AbstractRoutingDataSource {
@Autowired
private SecurityManager securitymanager;
private Map<Long, DataSource> targetDataSources = new HashMap<Long, DataSource>();
@SuppressWarnings({ "unchecked", "rawtypes" })
public void setTargetDataSources(Map targetDataSources) {
this.targetDataSources = (Map<Long, DataSource>) targetDataSources;
}
@Override
protected DataSource determineTargetDataSource() {
Long lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.targetDataSources.get(lookupKey);
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
@Override
protected Long determineCurrentLookupKey() {
try {
String username = securitymanager.getUserName();
Login login = null;
if (!StringUtils.isEmpty(username)) {
login = securitymanager.getLogin(username);
}
return login == null ? 1L : login.getConnexio() == null ? 1L : login.getConnexio().getId();
} catch (Exception e) {
return 1L;
}
}
@Override
public void afterPropertiesSet() {
// do nothing
// overridden to avoid datasource validation error by Spring
}
}
Используется в HibernateConfiguration так:
@Configuration
@EnableTransactionManagement
public class HibernateConfiguration {
@Autowired
private SecurityManager securitymanager;
@Autowired
private Parameters parameters;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean();
lcemfb.setDataSource(this.dataSource());
lcemfb.setPackagesToScan(new String[] { "cat.itec.pgm.persistence" });
lcemfb.setPersistenceUnitName("pgmdb");
HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
va.setShowSql(true);
lcemfb.setJpaVendorAdapter(va);
Properties ps = new Properties();
ps.put("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
ps.put("hibernate.format_sql", "true");
ps.put("hibernate.show_sql", "true");
lcemfb.setJpaProperties(ps);
lcemfb.afterPropertiesSet();
return lcemfb;
}
@Bean
public DataSource dataSource() {
RoutingDataSource rds = new RoutingDataSource();
Map<Long, DataSource> targetDataSources = new HashMap<Long, DataSource>();
List<Connexio> connexioLogins = new ArrayList<Connexio>();
try {
connexioLogins = securitymanager.getConnexioLogins();
} catch (Exception e) {
System.out.println("Cannot Load List Of Connections");
}
for (Connexio c : connexioLogins) {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(parameters.getDriverClassName());
ds.setUrl(generateUrlConnection(c));
ds.setUsername(c.getDbUsername());
ds.setPassword(c.getDbPassword());
targetDataSources.put(c.getId(), ds);
}
rds.setTargetDataSources(targetDataSources);
return rds;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
return tm;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private String generateUrlConnection(Connexio c) {
StringBuilder sb = new StringBuilder();
sb.append("jdbc:oracle:thin:@");
sb.append(c.getServer());
sb.append(":");
sb.append(c.getPort());
sb.append(":");
sb.append(c.getSid());
return sb.toString();
}
}
Дело в том, что, когда я начинаю сервера он бросает:
Caused by: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685)
at cat.itec.security.persistence.dao.login.impl.LoginDaoImpl.getConnexioLogins(LoginDaoImpl.java:37)
Я не знаю, как если ошибка сделать RoutingDataSource получить каждый «Connexio», или он не настроен правильно.
Любая помощь или комментарий будут оценены. (любой другой фрагмент кода, необходимый для лучшего понимания, будет опубликован, как только я смогу).
Заранее спасибо.
EDIT (неудобные, см edit2):
Изменение чуток две противоречивых точек базов данных, как это:
@Bean
public DataSource dataSource() {
RoutingDataSource rds = new RoutingDataSource();
Map<Long,DataSource> targetDataSources = new HashMap<Long,DataSource>();
Connexio c = new Connexio();
c.setDbPassword("XXXXXXXXX");
c.setDbUsername("XXX");
c.setId(1L);
c.setPort("XXXXXXX");
c.setServer("XXXXXXXX");
c.setSid("XXXX");
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(parameters.getDriverClassName());
ds.setUrl(generateUrlConnection(c));
ds.setUsername(c.getDbUsername());
ds.setPassword(c.getDbPassword());
targetDataSources.put(c.getId(), ds);
rds.setTargetDataSources(targetDataSources);
return rds;
}
И
@Override
protected Long determineCurrentLookupKey() {
return 1L;
}
делает приложение работает, как это было до этого. Таким образом, кажется, проблема с доступом к БД при запуске сервера. Есть идеи?
EDIT2:
изменил код добавлен в первый срок, чтобы отправить полный рабочий один в качестве примера.