您的位置:首页 > 编程语言 > Java开发

基于Java对象的数据库增删改查操作

2014-03-09 23:09 543 查看

目标:

让完全不懂数据库,不懂SQL的程序员,能轻松地进行数据库记录的增删改查操作。减少重复的DAO操作编码,提高开发效率。

分析:

一、表记录类型:

一般应用系统的表记录类型可以分为以下三类:

1 配置记录:记录着系统的一些配置参数。一般一个表只有一条记录,只需要实现读和写操作即可

2 增量记录:记录着实体的信息。一般都有一个ID作为主键,来唯一标识这条记录。需要提供增、删、改、查操作。

3 日志记录:记录着系统的运行状态,接口交换状态,操作记录等。一般都不需要索引,不需要唯一标识。需要提供写和查询操作即可。

4 关联记录:用于关联表与表之间多对多的关系。需要提供读取和设置操作。

二、表字段类型:

表的字段类型一般可以分为:布尔、数值、字符串、时间,TEXT和BLOB类型一般不用于检索。各类型的查询条件:

1 布尔:=

2 数值:=,>=,>,<,<=,<>

3 时间:同上。(一般是针对时间段的查询)

4 字符串:=,LIKE

设计:

一、PO对象的约束:

要求每个PO对象的成员数据和表的字段名相同,这样方便反射方式把数据字段和对象成员数据做对应。成员数据都必须是:

1 布尔:Boolean

2 数值:Byte(1),Short(2),Integer(4),Long(8),Float(4),Double(8)

3 时间:java.util.Date

4 字符串:String

5 BLOB:byte[]

下面分别对不同记录类型进行设计:

1 配置记录:不用做任何约束

2 增量记录:第一个数据为Integer id,作为记录的主键

3 日志记录:第一个数据为Date logtime,作为日志记录时间

4 关联记录:无需做PO

二、PO对象的操作:

PO对象一般涉及到增加、删除、修改、查询操作。增删改操作的参数相对比较简单,基本由一个PO对象作为参数即可。查询操作由于查询条件多种多样,需要传递比较多的参数。

查询:传递3个参数,第一个是查询描述参数,第二个是查询数据1,第三个是查询数据2。如Select(PO desc, PO data1, PO data2)。如果desc.field=null,该字段将不作为查询条件。各种字段类型的描述:

1 布尔:desc.field=true, 取data1.field

2 数值:=(1),<>(2),>=(3),<=(4),>= AND <=(5)。desc.field=前面的值,前面4个,只需取data1.field;第5个取data1.field 和 data2.field

3 时间:同上。desc.field= new Date(1)

4 字符串:desc.field="=" OR "LIKE"。取data1.field

查询的排序:排序分顺序(ASC)和倒序(DESC),支持多个字段的复合排序。

三、PO对象的关联

/**

* 多对多关联表,在删除时需要删除关联表的相关记录

*/

public class RelTable

{

/**

* 关联表表名

*/

String tablename;

/**

* 关联表对于本表的外键名

*/

String myfkeyname;

/**

* 关联表对于对方表的外键名

*/

String peerfkeyname;

}

四、接口设计:

1 配置记录的读与写:

/**

* 配置记录的DAO模板接口

*/

public interface CfgRecDao<PO>

{

/**

* 读记录

*/

public PO Read() throws Exception;

/**

* 写记录

*/

public void Write(PO data) throws Exception;

}

2 增量记录的增删改查:

/**

* 增量记录DAO模板接口

*/

public interface IncRecDao<PO>

{

//下面是PO desc的成员常量

public static final Boolean BOOL_EQU= true; //=

public static final String STRING_EQU="="; //=

public static final String STRING_LIK="~"; //LIKE

public static final Date DATE_BIGEQU= new Date(1); //>=

public static final Date DATE_SMAEQU= new Date(2); //<=

public static final Date DATE_BIGEQUandSMAEQU= new Date(3); //>= AND <=

public static final byte NUMERIC_EQU=1; //=

public static final byte NUMERIC_NOTEQU=2; //<>

public static final byte NUMERIC_BIGEQU=3; //>=

public static final byte NUMERIC_SMAEQU=4; //<=

public static final byte NUMERIC_BIGEQUandSMAEQU=5; //>= AND <=

public static final Boolean ORDER_BOOL_ASC= true;

public static final Boolean ORDER_BOOL_DESC= false;

public static final String ORDER_STRING_ASC="ASC";

public static final String ORDER_STRING_DESC="DESC";

public static final Date ORDER_DATE_ASC= new Date(1);

public static final Date ORDER_DATE_DESC= new Date(2);

public static final byte ORDER_NUMERIC_ASC=1;

public static final byte ORDER_NUMERIC_DESC=2;

/**

* 插入一条记录

* @param data: 数据对象,插入成功后得到主键值(id)

* @return: 无

* @throws Exception

*/

public void Insert(PO data) throws Exception;

/**

* 删除一条记录,同时删除多对多关联表里面的相关记录

* @param data: 数据对象,只需要有主键值(id)

* @return: 无

* @throws Exception

*/

public void DeleteByID(int id) throws Exception;

/**

* 删除一批记录

* @param arg: 查询条件,若为null,不删除

* @return: 无

* @throws Exception

*/

public void Delete(PO arg) throws Exception;

/**

* 更新一条记录

* @param data: 数据对象,需要有主键值(id)

* @return: 无

* @throws Exception

*/

public void Update(PO data) throws Exception;

/**

* 唯一查询

* @param arg: 查询条件,若为null,则不限条件

* @return: 返回一个符合条件的数据对象

* @throws Exception

*/

public PO SelectOne(PO arg) throws Exception;

/**

* 主键查询

* @param id: 主键查询

* @return: 返回一个符合条件的数据对象

* @throws Exception

*/

public PO SelectByID(int id) throws Exception;

/**

* 设置查询的排序方式

* @param desc: 为null的字段不做排序

* @throws Exception

*/

public void SetOderBy(PO desc) throws Exception;

/**

* 设置查询的唯一方式

* @param desc: 为null的字段不做唯一限制

* @throws Exception

*/

public void SetDistince(PO desc) throws Exception;

/**

* 全匹配复合查询

* @param arg: 查询条件,若为null,则不限条件

* @return: 返回符合条件记录数

* @throws Exception

*/

public int SelectCount(PO arg) throws Exception;

/**

* 全匹配复合查询

* @param arg: 查询条件,若为null,则不限条件

* @param offset: 在记录集的第几条开始返回,>=0

* @param count: 分页显示条数,若为0或负数,则返回所有记录

* @return: 返回一组符合条件的数据对象

* @throws Exception

*/

public PO[] Select(PO arg,int offset,int count) throws Exception;

/**

* 复合查询

* @param desc: 查询条件描述

* @param data1: 查询条件数据1

* @param data2: 查询条件数据2

* @return: 返回符合条件记录数

* @throws Exception

*/

public int SelectCount(PO desc,PO data1,PO data2) throws Exception;

/**

* 复合查询

* @param desc: 查询条件描述

* @param data1: 查询条件数据1

* @param data2: 查询条件数据2

* @param offset: 在记录集的第几条开始返回,>=0

* @param count: 分页显示条数,若为0或负数,则返回所有记录

* @return: 返回一组符合条件的数据对象

* @throws Exception

*/

public PO[] Select(PO desc,PO data1,PO data2,int offset,int count) throws Exception;

/**

* SQL直接查询

* @param sql: SELECT COUNT(*) 开头

* @return: 返回符合条件记录数

* @throws Exception

*/

public int SelectCountBySql(String sql) throws Exception;

/**

* SQL直接查询

* @param sql: SELECT * 开头

* @return: 返回一组符合条件的数据对象

* @throws Exception

*/

public PO[] SelectBySql(String sql) throws Exception;

///////////////////////// 关联表记录 /////////////////////////

/**

* 设置多对多关联表记录,在实体记录删除时,关联表记录自动删除

* @param thisid: id

* @param reltab: 关联表名及对方id

* @param fkeyids: 对方id

* @throws Exception

*/

public void SetRelationIds(int thisid,String reltab,int[] fkeyids) throws Exception;

/**

* 获取多对多关联id

* @param thisid: id

* @param reltab: 关联表名及对方id

* @throws Exception

*/

public int[] GetRelationIds(int thisid,String reltab) throws Exception;

/**

* 搜索多对多关关系的对象

* @param thisid: id

* @param reltab: 关联表名

* @param objtb: 目标表名

* @param objcls: 目标对象类型

* @return: 返回符合条件的数据对象,用Y[]类型转换

* @throws Exception

*/

public Object SelectRelationObjs(int thisid,String reltab,String objtb,Class<?> objcls) throws Exception;

}

3 日志记录的增加和查询:

/**

* 日志记录DAO模板

*/

public interface LogRecDao<PO>

{

/**

*写入日志记录

* @param data: 日志

*/

public void Insert(PO data) throws Exception;

/**

* 设置查询的排序方式

* @param desc: 为null的字段不做排序

* @throws Exception

*/

public void SetOderBy(PO desc) throws Exception;

/**

* 设置查询的唯一方式

* @param desc: 为null的字段不做唯一限制

* @throws Exception

*/

public void SetDistince(PO desc) throws Exception;

/**

* 复合查询

* @param desc: 查询条件描述

* @param data1: 查询条件数据1

* @param data2: 查询条件数据2

* @return: 返回符合条件记录数

* @throws Exception

*/

public int SelectCount(PO desc,PO data1,PO data2) throws Exception;

/**

* 复合查询

* @param desc: 查询条件描述

* @param data1: 查询条件数据1

* @param data2: 查询条件数据2

* @param offset: 在记录集的第几条开始返回,>=0

* @param count: 分页显示条数,若为0或负数,则返回所有记录

* @return: 返回一组符合条件的数据对象

* @throws Exception

*/

public PO[] Select(PO desc,PO data1,PO data2,int offset,int count) throws Exception;

}

4 工厂方法:

/**

* DAO模板工厂

*/

@SuppressWarnings("unchecked")

public class DaoFactory

{

/**

* 配置数据库连接参数

* @param dbcfg:数据库连接参数

* @throws Exception

*/

public static void ConfigDBC(DBconfig dbcfg) throws Exception

{

ConnectionPool.init(dbcfg);

}

/**

* 配置记录的DAO创建

* @param pocls: PO对象类型

* @param tbName: 数据库表名

* @return: 配置记录的DAO对象

* @throws Exception

*/

public static CfgRecDao<?> CreateCfgRecDao(Class<?> pocls,String tbName) throws Exception

{

return new CfgRecDaoImpl(pocls, tbName);

}

/**

* 增量记录的DAO创建

* @param pocls: PO对象类型

* @param tbName: 数据库表名

* @param pkname: 表的主键名

* @param reltables: 关联表名及键名

* @return: 增量记录的DAO对象

* @throws Exception

*/

public static IncRecDao<?> CreateIncRecDao(Class<?> pocls,String tbName,String pkname,RelTable[] reltables) throws Exception

{

if(pkname==null)

throw new Exception("Need primary key for table");

return new IncRecDaoImpl(pocls, tbName, pkname, reltables);

}

/**

* 日志记录的DAO创建

* @param pocls: PO对象类型

* @param tbName: 数据库表名

* @return: 日志记录的DAO对象

* @throws Exception

*/

public static LogRecDao<?> CreateLogRecDao(Class<?> pocls, String tbName) throws Exception

{

return new IncRecDaoImpl(pocls, tbName, null, null);

}

}

例程:

以用户,用户组,文件资源为例,为了给用户授权可以访问哪些文件资源,需要把用户赋予某个组,而对文件资源的访问权限,也由组去设置。这样,用户和组是多对多的关系,用户组和文件资源也是多对多的关系。PO类定义:

public class UserPO

{

public Integer id;

public String name;

public String account;

public String pwdsha1hex;

}

public class UserGroup {

public Integer id;

public String name;

}

public class FileResource {

public Integer id;

public String name;

public Date modifytime;

}
操作测试:
//插入、修改和删除测试
static void TestInsertUpdateAndDelete() throws Exception

{

IncRecDao<UserGroup> ugdao= TestCreateDAO();

UserGroup data= new UserGroup();

data.name= "insert测试";

ugdao.Insert(data);

System.out.println("Insert OK");
data.name= "update测试";

ugdao.Update(data);
ugdao.DeleteByID(data.id);

System.out.println("Delete OK");

}

//查询测试

static void TestSelect() throws Exception

{

IncRecDao<UserGroup> ugdao= TestCreateDAO();

UserGroup orderby= new UserGroup();

orderby.name= IncRecDao.ORDER_STRING_ASC;

ugdao. SetOderBy(orderby); //设置查询排序

UserGroup data1= new UserGroup();

data1.id=1;

int count= ugdao.SelectCount(data1);

UserGroup[] datas= ugdao.Select(data1, 0, 0);

System.out.println("Select count: "+count+"\r\n"+datas);
UserGroup desc= new UserGroup();

desc.id=IncRecDao.NUMERIC_BIGEQUandSMAEQU;

desc.name=IncRecDao.STRING_EQU;

data1.name="test";

UserGroup data2= new UserGroup();

data2.id=6;

count= ugdao.SelectCount(desc, data1, data2);

datas= ugdao.Select(desc, data1, data2, 0, 0);

System.out.println("Select count: "+count+"\r\n"+datas);

}



总结

本设计能满足基本的增删改查操作,对于一般的业务系统,基本够用。

一、长处:

1对比起其他O/R工具,比如Hibernate,不用做复杂的O/R配置,开发效率高。
2 直接以对象为参数进行查询,不用写查询语句,降低了对Java程序员数据库知识水平的要求。
3 通过模板类,对数据类型做了简单的检查,减少出错



二、不足之处:

1 不支持复杂的查询条件
2 因为运用了很多反射机制,性能上有所降低
3 对于复杂的业务逻辑,这里抽象出来的基本操作恐怕不够用,需要再扩展












内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: