多线程下谨慎对待基类(抽象类)中的成员变量

有这么个需求:
做开发一套在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中

我选择了后者。

你可能感兴趣的:(DAO,框架)