有这么个需求:
做开发一套在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中
我选择了后者。
分享到:
相关推荐
在实际项目中,这样的线程基类可以被子类化,以满足特定的需求。例如,你可以创建一个继承自CSimpleThread的子类,并在子类中重写`Run()`方法,以执行特定的业务逻辑。 为了更好地理解这个类的工作原理,你需要查看...
在Java编程语言中,抽象类和接口是两个重要的概念,它们用于实现代码的多态性和模块化设计。本文将深入探讨这两个概念,以及它们在Java全栈开发中的应用。 首先,我们来理解抽象类(Abstract Class)。抽象类是不能...
5. **接口与抽象类的区别**:对比两者在使用上的差异,包括继承的数量限制(一个类只能继承一个抽象类,但可以实现多个接口)和成员类型(抽象类可有实例变量,接口则没有)。 6. **适配器模式**:可能会介绍如何...
抽象类不能被实例化,它们通常作为其他类的基类,提供继承的结构。 3. **静态类**:静态类,也称为工具类,通常包含静态方法和静态变量。它们不能包含非静态成员,也不能被实例化。静态类中的方法可以通过类名直接...
`volatile`关键字用于修饰多线程环境中的变量,确保其可见性和有序性。实例变量与类变量相对,每个对象都有独立的副本。 方法是类中的行为,分为实例方法和类方法(静态方法)。`static`修饰的方法是类方法,它在类...
在C++编程中,多线程是一个核心概念,它允许程序同时执行多个任务,从而提高系统效率和响应性。在现代计算机系统中,多核处理器的普及使得多线程技术成为充分利用硬件资源的关键。本教程将重点介绍如何在C++环境中,...
在`vc6`环境下创建MFC多线程项目,你需要选择MFC AppWizard,并在向导中选择"单文档"或"多文档"应用程序,然后在工程设置中选择"多线程"选项。 为了使多线程协同工作,MFC提供了一些同步机制,如`CSemaphore`(信号...
在IT领域,多线程是程序设计中一个关键的概念,特别是在C++这样的面向对象编程语言中。多线程允许程序同时执行多个独立的任务,从而提高了系统资源的利用率和程序的执行效率。本实例集中展示了如何在C++环境中利用多...
抽象类用作其他类的基类,接口则提供了多继承的功能,使得类可以实现多个接口,从而实现多种行为。 2. **特征**:在Java中,特征通常指的是类的属性(成员变量)和行为(方法)。类的特征定义了对象的状态和操作。...
根据提供的标题“C++面向对象多线程编程”和描述“C++面向对象多线程编程,一本经典的学习资料,很好的”,我们可以理解这是一本关于使用C++进行面向对象及多线程编程的经典教程。虽然具体内容没有给出,但从标题和...
标题中的“用MFC编写VC多线程程序”是指在Microsoft Visual C++(VC)开发环境中,利用MFC(Microsoft Foundation Classes)库来构建多线程应用。MFC是微软提供的一个C++类库,它封装了Windows API,使得开发者能更...
在C++中,抽象类通常包含纯虚函数,不能实例化,用于作为其他类的基类。 接下来,我们转向多线程编程。多线程是在单个程序中同时执行多个独立的执行流,从而提高程序的并发性和效率。C++11引入了对多线程的支持,...
在"CaptureVideo.cpp"和"CaptureVideo.h"这两个文件中,通常cpp文件包含了类的实现细节,而h文件则是类的声明,包括类的定义、成员函数和变量等。以下是可能包含在这些文件中的关键知识点: 1. **类设计**:`...
- 抽象类可以有普通成员变量和静态成员变量。 - 接口只有公共静态常量。 3. **方法**: - 抽象类可以包含抽象方法(没有方法体)和非抽象方法(有方法体)。 - 接口中所有方法默认都是抽象的,且必须是公共的,...
在VB6中,虽然没有内置的抽象类概念,但可以通过定义纯虚方法(MustOverride)来实现类似的效果。 共享内存是一种多线程间的通信方式,允许不同线程访问同一块内存区域。在VB6中,可以使用全局变量或者模块级别的...
同时,抽象类是包含抽象方法(没有实现的方法)的类,可以作为其他类的基类,提供部分实现。 在Java中,异常处理是一个重要的话题。使用try-catch-finally结构可以捕获和处理运行时错误,保证程序的健壮性。异常...
3. **线程同步**:属性可以通过在`set`访问器中使用`lock`语句来实现线程同步,确保多线程环境下的数据一致性。 4. **抽象性**:属性可以被声明为抽象的,这意味着在基类中声明属性而不提供具体实现,留给派生类...
受保护区域是指在多线程环境中,为了防止并发访问而导致的数据不一致性,而使用同步机制(如锁)保护的代码段。通过确保每次只有一个线程可以访问受保护区域,可以有效地避免竞态条件。 #### 33. 堆 (Heap) 堆是...
8. **volatile**: 指定该变量具有易变性,可以被多线程访问和修改。它确保了变量的可见性和一定程度的原子性,但并不保证完全的原子性操作。 #### 四、总结 通过以上介绍,我们可以看到Java提供了丰富的特性和机制...