有这么个需求:
做开发一套在oracle和mysql中做业务数据复制,其中具体的业务还没确定,目前需要开发一套
框架,需要在业务确定后,只需做少了开发即可实现,我使用了ibatis+spring
,以后扩展时,只需增加ibatis的配置文件即可,而配置文件中的每个ID都是由以下规则生成:
业务识别码+新增/删除等统一的后缀。
如下结构:
1、DAO部分
public abstract class Base
{
private String name;
private String code;
public String getName(){return name;}
public String getCode(){return code;}
public void setName(String name){this.name=name;}
public void setCode(String code){this.code = code;}
public String getInsertSqlName()
{
return this.code+"insert";
}
public abstract insert(...);
public abstract query(...);
}
public class ADao extends Base
{
public map insert(...)
{
String sqlName = this.getInsertSqlName();
//用ibatis操作数据库
}
public map query(...)
{
xxxxx
}
}
public class BDao extends Base
{
public map insert(...)
{
String sqlName = this.getInsertSqlName();
//用ibatis操作数据库
}
public map query(...)
{
xxxxx
}
}
public class CDao extends Base
{
public map insert(...)
{
String sqlName = this.getInsertSqlName();
//用ibatis操作数据库
}
public map query(...)
{
xxxxx
}
}
2、Service部分
根据数据库配置动态创建DAO,大概如下:
String name=从数据库读取
String code = 从数据库读取
Base dao = ServFactory.getDao(name,code);
dao.insert(xxx);
dao.query(xxx);
3、为了重用DAO,如上面Service部分,使用ServFactory创建DAO,
原理就是将创建的DAO放到map中,在getDao前先检查map中有没有DAO,没有则创建。
单线程运行下没问题。
但是在并发处理时,发现查询出来的数据错位了,明明查A的数据,结果返回了B的数据。
使用debug跟踪发现,DAO中的name和code会在执行insert后的query被突然改变,原来在并发下有其他请求的code被其他获取相同DAO的线程改变,导致最后执行的SQL不是预期的SQL。
解决方法有2:
1、不缓存DAO,每次创建个新DAO
2、不适用Base的成员变量,直接将name和code通过参数传入到insert和query中
我选择了后者。