前幾天完成了一個很小的java項目,儘管項目很小,但是有不錯的設計,與大家分享下遇到的問題以及解決方案。
問題:項目中需要能夠操作多個數據庫,並且要有不錯的擴展性,隨時添加數據庫連接。
其實這個需求還是挺正常的,比如說:有一個網站在不同的地區涉及業務,而不同地區的數據存儲在不同的數據庫,並且日後擴展規模擴展區域會增添數據庫。
首先想到的是使用Spring來管理MyBatis的SqlSession,因爲最近項目也一直使用Spring,但是Spring容器初始化之後,很難再添加數據源,而且多個數據庫在Spring中xml配置文件需要複製多份datasource,sqlSessionFactory以及sqlSession,代碼很不優雅,擴展不足。
隨後設想使用MyBatis自己來創建SqlSessionFactory以及SqlSession,MyBatis創建SqlSessionFactory是通過讀取xml配置文件,每個數據源使用一個配置文件,增加一個配置文件也就能夠動態增加一個SqlSession(數據連接)。
部分代碼如下:
area_one.xml中的主要配置(<mappers> 等配置省略):
<configuration >
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:localhost:3306/area_one?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
area_two.xml中的主要配置(<mappers> 等配置省略):
<configuration >
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:localhost:3306/area_two?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
CustomSqlSessionFactoryBuilder類用來根據xml配置文件創建SqlSessionFctory,並且據此創建SqlSession對象
public class CustomSqlSessionFactoryBuilder
{
public static void buildSqlSessions() // 靜態方法,用來創建以及更新所有的SqlSession,當有新增的xml配置文件添加到res文件夾時更新SqlSesion集
{
File resource_directory = new File("res"); // 讀取資源文件夾(xml配置文件保存於資源文件夾res中)
File[] resources = resource_directory.listFiles();
for(File resource : resources) // 循環所有配置文件
{
if(resource.getName().endsWith(".xml"))
{
System.out.println(resource.getName());
if(!CustomSqlSessionHolder.getExistedSqlSessions().keySet().contains(resource.getName())) //CustomSqlSessionHolder類保存已有的SqlSession,若已存在則跳過
{
try
{
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
InputStream is = Resources.getResourceAsStream(resource.getName());
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
String key = resource.getName().substring(0, resource.getName().indexOf(".xml"));
CustomSqlSessionHolder.getExistedSqlSessions().put(key, sqlSession); // 以地區的名字爲key,對應的SqlSession對象爲value進行存儲
System.out.println(sqlSessionFactory);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
System.out.println("SqlSessionHolder Updated!");
}
CustomSqlSessionHolder類用來保存現有的SqlSession,以及當有新增的xml配置文件添加到res文件夾時更新SqlSesion集合
public class CustomSqlSessionHolder
{
private static Map<String, SqlSession> sqlSessions = new HashMap<String, SqlSession>();
public static Map<String, SqlSession> getExistedSqlSessions()
{
return sqlSessions;
}
public static void updateSqlSessions()
{
CustomSqlSessionFactoryBuilder.buildSqlSessions();
}
public static SqlSession getNeededSqlSession(String area_name)
{
return getExistedSqlSessions().get(area_name);
}
}
可以開啓一個線程一天(或12小時,其他固定時間段)運行一次CustomSqlSessionFactoryBuilder.buildSqlSessions()。
這個小項目中仍然使用了Spring不過是用作他途,真正的管理SqlSession主要代碼如上,
擁有不錯的擴展性與配置性。項目發佈到服務器上,使用cron定期執行數據庫操作。
One Week Has Gone, Good Bye, Readers! See You Next Post.....