有这么个需求:
做开发一套在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中
我选择了后者。
分享到:
相关推荐
ThreadImRunnable.java 继承Runnable接口实现多线程 mulThread.java 创建多个线程对象的类 demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类...
0062 如何利用抽象类进行数据封装 25 0063 数据类型与类对象大小的区别 26 0064 实现类的强制转换 26 1.8 高级函数 27 0065 如何重载操作符 27 0066 如何定义重载函数 28 0067 默认构造函数 28 0068 ...
245 12.3.3 在外部类外访问静态内部类 246 12.4 匿名内部类 247 12.4.1 创建匿名内部类 247 12.4.2 匿名内部类的初始化 249 12.5 综合练习 250 12.6 小结 250 12.7 习题 250 第13章 多线程(精彩视频:55分钟) 252 ...
//包的定义 Import java.awt.Color //导入包关键字Import 4、接口 、接口的定义 Java中的接口可以看成是一种抽象类,它是一些抽象方法和常量的集合,其主要作用 是使得处于不同层次上以至于互不相干的类能够执行...
//包的定义 Import java.awt.Color //导入包关键字Import 4、接口 、接口的定义 Java中的接口可以看成是一种抽象类,它是一些抽象方法和常量的集合,其主要作用 是使得处于不同层次上以至于互不相干的类能够执行...
//包的定义 Import java.awt.Color //导入包关键字Import 4、接口 、接口的定义 Java中的接口可以看成是一种抽象类,它是一些抽象方法和常量的集合,其主要作用 是使得处于不同层次上以至于互不相干的类能够执行...
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
多线程,用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用? 59.使用socket建立客户端与服务器的通信的过程 60.JAVA语言国际化应用,Locale类,Unicode 61.描述反射机制的作用 62.如何读写一个...
Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 接口(interface)是抽象类的变体。在接口中,所有方法...
默认情况下存在一个全局命名空间,所以在命名空间外定义的类直接进到此全局命名空间中,因而你可以不用定界符访问此类。 你同样可以定义嵌套命名空间。 Using #include 指示符被后跟命名空间名的 using 关键字代替...
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
6.3 抽象类 6.4 所有类都从system. object派生 6.5 使用is运算符验证基础类型 6,6使用as运算符进行转换 6.7 小结 第7章 接口 7.1 接口概述 7.2 通过接口来实现多态性 7.3 接口实现 7.3.1 显式成员实现 ...
6.3 抽象类 204 6.4 所有类都从System.Object派生 208 6.5 使用is操作符验证基础类型 209 6.6 使用as操作符进行转换 210 6.7 小结 211 第7章 接口 213 7.1 接口概述 213 7.2 通过接口实现多...
java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...
8.12 定义接口或者抽象基类 8.13 实现数据模型的类型约束 8.14 实现自定义容器 8.15 属性的代理访问 8.16 在类中定义多个构造器 8.17 创建不调用init方法的实例 8.18 利用Mixins扩展类功能 8.19 实现状态...