【发布时间】:2015-04-30 05:26:14
【问题描述】:
我正在尝试仅使用一个数据源更改注释休眠状态,以使尽可能多的数据源保存在数据库中。为了使用户拥有分配的连接,并添加新类型的连接,只需重新启动服务器(避免 .war 重新编译)
服务器首先加载一个 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());
}
}
然后我创建了一个这样的路由数据源:
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”,还是没有正确配置。
任何帮助或评论将不胜感激。 (我会尽快发布任何其他需要更好理解的代码)。
提前致谢。
编辑(无用,参见 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:
更改了第一学期添加的代码,以发布完整的工作代码作为示例。
【问题讨论】:
标签: hibernate spring-mvc spring-security spring-3 spring-annotations