|
A.查询
数据引擎的传递参数可分为三类,map对象、实体对象和Param对象,其中Param是引擎的条件参数类,它可以构建灵活多样的条件。下面分别举例演示。
a.获取单条记录
以map对象作参数
|
Map map=new HashMap();
map.put(“sid”,1);//查询字段sid值为1的记录
//获取Map对象的结果
Map student = DataCenter.getMap(“student”,map);
//获取实体对象的结果
Student student = DataCenter.getObject(“student”, map, Student.class);
|
以实体对象作参数
|
Student st=new Student();
st.setSid(1);
//获取Map对象的结果
Map student = DataCenter.getMap(“student”,st);
//获取实体对象的结果
Student student = DataCenter.getObject(“student”, st, Student.class);
|
以Param对象作参数
|
//获取Map对象的结果。查询student表(单主键)中主键为1的记录,以下三种方式等效
Map student = DataCenter.getMap(“student”,1);//直接以具体的值当参数
Map student = DataCenter.getMap(“student”,new Param(“sid”,1));
Map student = DataCenter.getMap(“student”,new Param().add(“sid”,1));
//获取实体对象的结果。查询student表中主键为1的记录,以下三种方式等效
Student student = DataCenter.getObject(“student”,1, Student.class);
Student student = DataCenter.getObject(“student”,new Param(“sid”,1), Student.class);
Student student = DataCenter.getObject(“student”,new Param().add(“sid”,1), Student.class)
|
|
//如果不是按主键查询,可能有多条符合条件的记录,但只会返回第一条
Param pm=new Param();
pm.add(“name”,”李伟”);//查询name为李伟的记录
//pm.add(“name”,”=“,”李伟”);//与上句的写法完全等效
Map student = DataCenter.getMap(“student”,pm);//返回Map
Student student = DataCenter.getObject(“student”,pm, Student.class);//返回实体
|
b.查询多条记录
获取多条记录的参数设置与单条记录完全一样,只是调用的方法名不一样。
|
//获取name是李伟,并且age大于20的所有记录
Param pm=new Param();
pm.add(“name”,”李伟”);
pm.add(“age”,”>“,20);
List<Map> list= DataCenter.getMapList(“student”,pm);//返回map结果集
List<Student> list= DataCenter.getObjectList(“student”,pm, Student.class);//返回实体结果集
|
|
//获取name是李伟,或者age为20的所有记录
Param pm=new Param();
pm.add(“name”,”李伟”);
pm.addOr(“age”,20);
List<Map> list= DataCenter.getMapList(“student”,pm);//返回map结果集
List<Student> list= DataCenter.getObjectList(“student”,pm, Student.class);//返回实体结果集
|
|
//获取birthday不在2000-4-1到2000-4-30之间的所有记录
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date da1=df.parse("2000-04-01");
java.util.Date da2=df.parse("2000-04-30");
pm.addNotBetween("birthday", da1, da2);
List list = DataCenter.getMapList("student", pm);
//对于mysql来说,可以直接传递日期串,即可以这样设置条件:
pm.addNotBetween("birthday", "2000-04-01", "2000-04-30");
//如果是查询某范围内的值,使用下句,生成的sql为between ..and ..
pm.addBetween("birthday", da1, da2);//与上句正相反,
|
如果不传参数,获取的是全部记录
|
List<Map> list= DataCenter.getMapList(“student”);//返回map结果集
List<Student> list= DataCenter.getObjectList(“student” , Student.class);//返回实体结果集
|
c.参数类Param详解
Param是参数类,通过它可构建多种sql 的where条件,列举如下:
pm.add(“age”,”<>“,30);//age不等于30
pm.addOr(“age”,”>=“,30);//或者(or) age大于等于30
pm.addBetween(“age”,20,30);//年龄在20和30间,包含20和30
pm.addNotBetween(“age”,20,30);//年龄不在20和30间,即<20并且>30
pm.add(“name”,”like”,”%张%”);//name含’张’
pm.add(“name”,”like”,”张%”);//name以’张’开头
pm.add(“name”,”not like”,”%张%”);//name不含’张’
pm.add(“name”,”is”,null);//name 的值为null
pm.add(“name”,”is not”,null);//name 的值不为null
pm.add(“name”, “in”, “'张三','李四','王五'”);//name为所列的三个值
pm.add(“name”, “not in”,“'张三','李四','王五'”);//name不是所列的三个值
pm.add(“age”, “not in”,“20,30,40”);//age不等于所列的三个值中的任意一个
如果in 或not in后所列的值很多,可以用list:
List list=new ArrayList();
list.add(“张三”);
list.add(“李四”);
list.add(“王五”);
pm.add(“name”, “in”,list);
参数条件最终会生成sql,先加的会出现在sql的靠左边。其中涉及的关系符与sql是一样的,包括:>,=,<=,<>,(not)like,(not)in,is(not),含not时,与邻词间有空格。
在一次查询请求中,不能对同一个字段进行一次以上的定义,否则只有最后添加的条件有效。例如,如果想查询age在20-30间或大于40的所有记录,以下不行:
pm.addBetween(“age”,20,30);
pm.addOr(“age”,”>“,40);
这种情况下,可以这样使用:
pm.addAsItIs(“age between 20 and 30 or age >40”);//标准的sql语法
在上面所列的各个查询中,默认查询的是所有字段,如果一张表字段很多,或者有大对象字段,并且实际上只需要用到其中很少的字段,这种做法从性能上看就不合理了,需要作限制:
Param pm=newParam();
pm.addField(“name,age”);//只查询name和age字段的值
如果需要查询大多数字段,只有少数不需要,可以采用排除法
pm. setExcludeColumn(“photo, birthday”);//排除photo和birthday两个字段,查询所有其它的字段
可以看到,多个字段间是以英文逗号分隔的。
如果上下文中已经有了待查询的指定字段的数组,可以set进param中,
假如有了数组:String[] fields={“name,age”};
pm. setFields(fields);//与pm.addField(“name,age”)等效
如果查询时,想去除重复:
pm. addDistinctField(“name”);
生成的sql类似这样:select distinct name from table where..
如果想对结果集排序:
pm. addOrderby(“sid desc,age asc”);//按sid降序,age升序排列
如果只想取部分记录,即所谓的分页查询:
pm. setPage(1,10);//从第一条记录开始,取10条
需要注意的是,如果是mysql数据库,分页查询返回的是map对象的结果集,则list最后一个元素map的key为'_total_',值为本次符合查询条件的记录总数。
构建Param时可以连写,例如下面查询条件是取name和age字段,age小于30,取第10到第60条记录,按age升序排列。
Param pm=new Param().add(“age”,“<“,30).
addField(“name,age”).setPage(10,50).addOrderby(“age”);
也可直接用条件作参数生成Param对象:
Param pm=new Param(“name”,“<>“,”张三”);
pm.addBetween(“birthday”,”1980-01-01”,”1980-12-31”);
生成的条件是:name不为张三,并且是在1980-01-01到1980-12-31期间出生的。
在实际应用中,如果上下文中已经有了实体对象或map对象,可以用之直接构建Param对象,然后就可以充分利用param的其它功能了:
Param pm=new Param(map);//map对象
Student st=...//来自其它地方生成的实体对象
Param pm=new Param(st);//实体对象
pm.setPage(..);//进一步作其它需要的设置
如果构建一个Param对象完成查询后,想重复使用该对象,而条件稍有不同,可以这样:
pm.remove(“name”);//移除name的限制条件
pm. removeField(“name”);//移除name的限制查询字段,即移除setField的设置
pm. removeAllField();//移除全部的限制查询字段
pm.reset();//重置,所有的条件或设置全清除
d.获取记录数
|
//获取符合条件的记录数
Param pm=new Param(“class_id”,5);
int count= DataCenter .getRecordCount(“student”,pm); //统计所有在5班的学生数
int count= DataCenter .getRecordCount(“student”);//无条件参数类时,获取全部记录数
|
e.迭代取数
如果要取的记录数很多,但又不必全部放在内存,引擎采取只将主键放内存,需要具体内容时再次读取。(当然如果是海量数据,主键也会占大量内存,需控制条件。)
下面pm是Param对象,构建方式与上面相同,如果不传pm,则获取的是全部记录。
|
Iterator<Map<String, Object>> iter=DataCenter.getMapListIterator("student", pm);
//Iterator< Student > iter=DataCenter.getObjectListIterator("student ",pm, Student.class);
while (iter.hasNext()) {
Map stu=iter.next();
String name=(String)stu.get(“name”);
//Student stu=iter.next();
// String name=stu.getName();
. . .
}
|
f.获取其它形式的数据
获取xml格式的数据:
|
String data= DataCenter.fetchXmlData("student", pm);
|
获取指定字段与记录映射的数据
在实际应用中,有时获取到了记录集后,想取其中的一条记录,通过循环结果集当然可以,但更简单的方式如下:(参数中sid为表的主键名)
|
Map<String, Map> data=DataCenter .getMapListMap("student", pm,”sid”);
Map student=data.get(10);//取主键值为10的记录
String name=( String)student.get(“name”);//获取具体的各字段值
|
获取大对象的流数据
|
// photo大字段,如果符合pm条件的记录超过一个,取第一个
InputStream is= DataCenter .getLobStream("student",”photo”, pm);
|
g.判断记录否存在
虽然按上面的查询,根据是否有数据可以判断记录的存在,但性能更好的方式如下:
|
//判断是否有符合条件的记录(pm为Param对象,构建方式可参考前文)
boolean flag= DataCenter.isExist(“student”,pm);
|
h关联查询
前面都只涉及单一的表,有主从关系时,稍微复杂些,引擎提供两种方式实现关联查询,一种就是通过Param实现,下面就介绍,一种通过xml配置实现,类似hibernate做法,在后边的SQL操作中有介绍。
假如student与班级表school_class是一对一的关联,与课程表lesson是一对多的关联,为简单起见,school_class只有两个字段,一个是主键cid,一个是名称name,通过主键关联。lesson有三个字段,主键lid、关联字段sid和name,通过sid与student的sid进行关联。三张表都是单主键。在Student实体类中增加两个复合属性:
private SchoolClassschoolClass;
private List<Lesson>lessonList;
进行关联查询的关键就在Param中设置条件,例如:
|
Param pm=new Param();
pm.add("sid", 5);
//设置通过主表student的外键class_id关联到从表school_class的主键
pm.setLinkOne("class_id","school_class",SchoolClass.class);//one-one
//设置通过主表student的sid关联到从表lession的sid
pm.setLinkMany("sid", "lesson", "sid", Lesson.class);//one-many
Student sd=DataCenter.getObject("student",pm, Student.class);
SchoolClass schoolClass = sd.getSchoolClass();//获取关联属性
List<Lesson> lessonList = sd.getLessonList();//获取关联属性
//如果将上述各调用的最后一个参数Class去掉,将获得Map类型的结果
Map map=DataCenter.getObject("student",pm);
//获取复合属性的方式有点特别,是通过以表名_Map、表名_List作key来获取的
Map school=(Map)map.get("school_class_Map");
List lessionList=(List)map.get("student_lesson_List");
|
如果Param设置了延迟加载(后面有详述),那么主记录将不会加载复合属性,只有在真正去获取从表属性的值时,才会再次从库中读取。
如果是多对多的情况,需要用到中间表,有下面的方法可设置:
setLinkMany(String
linkTable,StringmiddleTable,StringmiddleFromField,
StringmiddleToField)
linkTable :关联的目标表名
middleTable 中间表名,中间表一般含两个字段
middleFromField 中间表中与主表主键进行关联的字段名
middleToField 中间表中与目标主键进行关联的字段名 |