前几天完成了一个很小的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.....