我们的应用程序可能有多个数据库。对于同一应用程序实例,数据库可以是不同类型(Oracle和MS SQL)。数据库结构略有不同,但使用了相同的Hibernate POJO集。列表od数据库只能在应用程序实际启动时确定(因此不能存储为固定的XML)
用户需要在登录过程中选择数据库。所选的数据库存储在HTTP会话中。
所以我想使用Sping自动布线将会话工厂自动连接到Web控制器中的DAO取决于当前用户。像:
@Repository
@Transactional
@Controller
public abstract class UserGroupDAO {
@Autowired
@Qualifier("sessionFactory")
private SessionFactory sessionFactory;
public List<Users> getListOfUsers() {
Session session = sessionFactory.currentSession();
return session.createCriteria(Users.class).list();
}
}
@Controller
public class WebController {
@Autowired
@Qualifier("userGroupDAO")
private UserGroupDAO userGroupDAO;
@RequestMapping("/greeting.html")
public ModelAndView greeting(Model model) {
userGroupDAO.getListOfUsers();
}
例如:有2个DB - Oracle_DB和MS_SQL_DB以及两个用户A和B.用户A登录Oracle_DB,用户B登录MS_SQL_DB。当用户A遇到/问候时,他应该看到来自Oracle_DB的用户列表,当用户B遇到/问候时 - 来自MS_SQL_DB。
我查看了AbstractRoutingDatasource,但它看起来只适用于具有多个数据源的单个会话工厂。但是,我正在为每个数据源(以及事务管理器)寻找单独的会话工厂。
提前感谢您的帮助
问题摘要
数据库是动态生成的,因此无法将数据库设置硬编码到配置文件中。 Spring应用程序需要能够确定哪些数据库可用,然后连接到它们。
答案 0 :(得分:0)
解决方案是 1)将UserGroupDAO,SessionFactory等范围设置为&#39; session&#39;
@Repository
@Transactional
@Scope(value="session",proxyMode=ScopedProxyMode.TARGET_CLASS)
public class UserGroupDAO extends GeneralDAO {
2)在Singleton(DataSourceProvider)中手动初始化SessionFactory,Session等,并从ApplicationContextConfig中的Singleton中获取它
@Configuration
@ComponentScan(....)
@EnableTransactionManagement
public class ApplicationContextConfig {
@Autowired
@Bean("sessionFactory")
@Scope(value="session")
public SessionFactory getSessionFactory(DataSource dataSource) {
return DataSourceProvider.getInstance().getDatasourceByContext().getSessionFactory();
}
@Autowired
@Bean("dataSource")
@Scope(value="session")
public DataSource getDataSource() {
return DataSourceProvider.getInstance().getDatasourceByContext().getDataSource();
}
3)检测DataSourceProvider中的当前数据库
public class DataSourceProvider {
private static DataSourceProvider instance = new DataSourceProvider();
public static DataSourceProvider getInstance() {
return instance;
}
private HashMap<String, MyDataSource> dataSources;
private DataSourceProvider(){
}
public MyDataSource getDatasourceByContext() {
String connectionName;
if (RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
if (request==null) {
connectionName = null;
} else {
//"currentDatabase" is set during logon
connectionName = (String)request.getSession().getAttribute("currentDatabase");
}
} else {
connectionName = null;
}
if (connectionName!=null) {
MyDataSource dataSource = dataSources.get(connectionName);
if (dataSource != null) {
return dataSource;
}
}
throw new IllegalStateException("No datasource for the context");
}