基于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 对于复杂的业务逻辑,这里抽象出来的基本操作恐怕不够用,需要再扩展
相关文章推荐
- PHP程序中使用PDO对象实现对数据库的增删改查操作的示例代码
- PHP程序中使用PDO对象实现对数据库的增删改查操作(PHP+smarty)
- java实现hbase数据库的增删改查操作(新API)
- 怎样在JAVA 中封装数据库操作(增删改查)运用反射机制!已贴出删除和查询方法,求增加和修改!
- java通过JDBC连接数据库及增删改查操作
- PHP程序中使用PDO对象实现对数据库的增删改查操作的示例代码
- java操作cassandra数据库(增删改查)
- Java+MyEclipse+Tomcat (六)详解Servlet和DAO数据库增删改查操作
- java中如何操作数据库(增删改查)
- 基于Java的XML文件模拟数据库进行增删改查操作
- 【经典】C#常用数据库操作(增删改查)
- MyBatis对数据库的增删改查操作,简单演示样例
- JAVA数据库操作3(CallableStatement对象)
- java连接mysql数据库 三 实现增删改查操作
- PHP实现基于面向对象的mysqli扩展库增删改查操作工具类
- lavavel连接数据库的增删改查操作
- 散列表的C程序实现,基于数组实现可以实现增删改查操作,
- JDBC连接数据库及增删改查操作
- MyBatis第二讲学习笔记 ,使用MyBatis对表执行增删改查操作——基于注解的实现
- Java连接Mysql数据库增删改查操作