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

本文探讨了在并发环境中使用缓存DAO模式时遇到的问题,特别是在Oracle和MySQL间进行业务数据复制的应用场景下,介绍了如何避免因代码共享导致的数据错乱,并提出了两种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

我选择了后者。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值