2014-10-09 37 views
1

我們的應用程序可能有多個數據庫。對於相同的應用程序實例,數據庫可能是不同的類型(Oracle和MS SQL)。數據庫結構略有不同,但使用了相同的Hibernate POJO集合。只有在應用程序實際啓動時才能確定列表od數據庫(因此不能將其存儲爲固定的XML)Spring + Hibernate:如何動態處理Multiply(Unlimited)數據源和會話工廠?

用戶需要在登錄過程中選擇一個數據庫。所選數據庫存儲在HTTP會話中。

所以我想使用Sping自動佈線來讓Web控制器中的Session Factory自動連接到我的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個數據塊 - Oracle_DB和MS_SQL_DB和兩個用戶A和B,用戶A登錄Oracle_DB,用戶B登錄MS_SQL_DB。當用戶A打/打招呼時,他應該從MS_SQL_DB中看到來自Oracle_DB的用戶列表,當用戶B點擊/問候語時。

我回顧了AbstractRoutingDatasource,但它看起來像只適用於具有多個數據源的單個Session Factory。不過,我正在爲每個數據源尋找單獨的會話工廠(以及事務管理器)。

預先感謝您的幫助

問題摘要

數據庫是dynamicaly由此產生不能硬編碼數據庫設置爲配置文件。 Spring應用程序需要能夠確定哪些數據庫可用,然後連接到它們。

+0

你可以將你的帖子改寫成問題嗎?大多數人不會回答問題,如果他們不知道你在問什麼,他們就不會回覆。 – JaneGoodall 2014-10-09 01:09:13

+0

你想要的是某種形式的多租戶。我幾年前爲客戶使用的一種解決方案被記錄在[這裏](http://mdeinum.wordpress.com/2007/01/05/one-application-per-client-database/)。該代碼可在[github](https://github.com/mdeinum/spring-utils)上找到,您可能對'multi-tenant'項目感興趣。 – 2014-10-09 06:09:23

回答

0

將溶液 1)設置UserGroupDAO,會話工廠等範圍到 '會話'

@Repository 
@Transactional 
@Scope(value="session",proxyMode=ScopedProxyMode.TARGET_CLASS) 
public class UserGroupDAO extends GeneralDAO { 

2)初始化的SessionFactory,會話等在一個Singleton(DataSourceProvider手動地),並從該得到它單在ApplicationContextConfig

@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"); 
} 
當前DB