java数据引擎(五):详细使用
来源:互联网 发布:nba2k13捏脸详细数据 编辑:程序博客网 时间:2024/06/03 23:06
1. xml SQL操作
上面所述的查询等操作,都是较单纯的数据操作,如果涉及多表关联查询、子查询、判断查询、数据库的特殊语句及函数调用,显然采用之前的方式是不行的。
数据引擎吸取了mybatis的思想,可以配置sql,但使用过程是简化了的。
虽然增删改也可以采用配置sql实现,但失去了数据引擎的简洁的思想,因为那样的话与mybatis基本没什么两样了。不过下面还是要介绍的。
A.配置
在类路径(如xml)下创建一个扩展名为.sql.xml的文件,这里叫test.sql.xml。
文件的内容像下面这样:
<?xmlversion="1.0"encoding="UTF-8"?>
<sqlsnamespace="testsql">
<sqlid="queryList">
select * from studentwhere sid<![CDATA[>]]>?
</sql>
<sqlid="getCount">
selectcount(*) ct from student where age=18
</sql>
</sqls>
在上面提到的udbcConfig.xml中将这个sql文件引入:
<dataSource>
…
</dataSource>
<sqlConfig>
<sql resource="/xml/test.sql.xml" />
<!--如果/xml下有多个.sql.xml 文件,使用下面的一行就可以-->
<sqlresource="/xml/*"/>
</sqlConfig>
B. 简单操作
看看如何调用上面test.sql.xml中的两个简单的sql。
String sqlid=”testsql.getCount”// namespace.id
List<Map<String, Object>>list=DataCenter.queryMapList(sqlid);
int count=(Integer)list.get(0).get(“ct”);//获取结果数
Object[] args=new Object[] {10};//对应于问号?参数的值
String sqlid=”testsql.queryList”;
List<Map<String, Object>>list=DataCenter.queryMapListParam(sqlid,args);
这是封装为Map的对象集,如果要得到实体对象集,可以这样:
List<Student> result=DataCenter.queryObjectListParam(sqlid, args, Student.class);
需要注意的是,如果表字段与实体的属性名不相同,需要使用别名形式的sql,
例如:selectname ,class_id classid,age from student,这样,class_id字段的值才会写入到实体类的classId中。
如果sql中不带问号?参数,调用方法是:
DataCenter. queryMapList (sqlid);
DataCenter.queryObjectList(sqlid, Student.class);
C. 复杂操作
使用配置的sql可以应对任意复杂的业务需求,而且一个配置sql可以根据条件生成若干具体的sql语句,用来当条件的参数与前述的一样,也是Map对象或实体对象,这里没有使用到Param类。能生成多条语句的特性与ibatis的做法一样,用的是动态标签(下面有专门总结),语句中也是使用##或$$分隔参数名,但每个语句只有一个id,没有像ibatis那样的传入、传出参数配置,也没有映射结果map的配置,没条语句的标签都是<sql>,不分select、update、delete 、insert等。
假如有这样的配置sql:
<sql id="dynamicsql">
select * from studentt
<dynamicprepend="where">
<isNotNullproperty="name"prepend="and">
t.name like'%$name$%'
</isNotNull>
<isNotNullproperty="age"prepend="and">
t.age<![CDATA[<]]>#age#
</isNotNull>
</dynamic>
order by t.sid
</sql>
调用:
Map map = new HashMap();
map.put("name","zhang");
map.put("age", 18);
List<Map<String,Object>> result = DataCenter.queryMapList("testsql.dynamicsql", map);
上面生成的sql是:select * from student t where t.name like'% zhang%' and t.age <18
如果map不放这句:map.put("name", "zhang"),那么生成的语句就是
select * from student t wheret.age <18
如果没有map.put("age", 18),生成的则是select * from student t wheret.name
like '% zhang%'
如果map没有任何键,或者干脆不要参数map,只传入sql的id,那么生成的是:
select * from student
要得到实体结果集(注意字段的属性别名使用):
List<Student> result=DataCenter.queryObjectList(sqlid,map,Student.class);
在test.sql.xml中加入如下的配置:
<sqlid="insert1">
insert into student (sid,name,age)values(?,?,?)
</sql>
<sqlid="insert2">
insert into student (sid,name,age) values(#sid#,#name#,#age#)
</sql>
以上两个语句都是用来向student插入记录的,调用如下:
Object[] args=new Object[3];
args[0]=300;
args[1]="chengsx";
args[2]=20;
intc=DataCenter.exeAdd("testsql.insert1", args);
Map map=new HashMap();
map.put("id", 400);
map.put("name","wang");
map.put("age", 18);
intc=DataCenter.exeAdd("testsql.insert2", map);//也可使用实体对象做参数
以上两种插入方式的区别在于,前者在构造参数时需要要严格的顺序,后者则没有此限制。
当需要批量插入记录时,可调用exeAddBatch(String sqlId,List<Object[]>paramArgs)
关于修改、删除的方法,与上面类似,不一一写sql了:
//修改操作,record中含有sql里用##或$$界定的属性及值
exeEdit(String sqlId,Objectrecord)
//修改操作,record中含有sql里用##或$$界定的属性及值,paramValues含占位参数(即?参数)所对应的值
exeEdit(String sqlId,Objectrecord,Object[] paramValues)
//批量修改操作,record中含有sql里用##或$$界定的属性及值,paramArgs是多个?参数所对应的值
exeEditBatch(StringsqlId,Object record,List<Object[]> paramArgs)
以下删除方法的参数意义与修改方法的参数是一样的:
exeRemove(String sqlId,Objectrecord)
exeRemove(String sqlId,Objectrecord,Object[] paramValues)
exeRemoveBatch(StringsqlId,List<Object[]> paramArgs)
exeRemoveBatch(StringsqlId,Object record,List<Object[]> paramArgs)
当xml定义的sql是查询功能时,为了获取其查询的记录数(用于分页),可调用
intcount=getRecordCountBySqlId(sqlid);
这样就不必再定义一个获取记录数的sql了。
获取记录数的方法提供了多种重载的形式。
D.配置方式的关联查询
前面提到的关联查询完全通过Param类来实现,也可以像hibernate那样通过配置文件来实现,首先创建文件,tab.maping.xml, (maping.xml是约定使用的扩展名)内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<tables>
<tablename="student">
<!-- one-to-one -->
<mapingproperty="schoolClass"relTable="school_class"relClass="test.SchoolClass"
srcField="class_id"relField="cid"lazy="true"/>
<!-- one-to-many -->
<mapingproperty="lessionList"relTable="lession"relClass="test.Lession"
srcField="sid"relField="sid"lazy="false"/>
<!-- many-to-many使用中间表关联-->
<!-- srcField和relField可以不定义,将自动采用主键名-->
<mapingproperty="lessonList"relTable="lesson"srcField="sid"relField="lid"middleTable="student_lesson"middleFromField="sid"middleToField="lid"relClass="test.Lesson" lazy="true"/>
</table>
</tables>
在总配置文件udbcConfig.xml中引入上述文件:
<!--关联映射配置-->
<mapingConfig>
<map resource="/xml/tab.maping.xml"/>
</mapingConfig>
经过这样配置后,当在查询时,引擎会自动加载关联属性,调用方式与其它查询一样,看参考前文。
当lazy配置为false时,只有第一层级查询会是即时加载,更深层的查询仍然是延迟加载。
如果lazy的值为false,只有查询单个记录对象时(getMap,getObject),才是即时加载,如果是获取多个对象,仍然是延迟加载。
使用getMap获取结果对象时,如果在Param设置限制字段时,没有包含主键,谈不上延迟加载功能。
获取map数据时,设置延迟加载,如果返回的结果是一条记录,应该转型为Map,而不是List。
如果既在xml配置了关联映射,又在Param中设置了映射,那么以Param的为主,忽略xml的配置,
当xml的配置生效时,如果获取的Map结果对象,复合属性的名称采用的就是配置中的指定名称。
E.构建动态语句的标签
下面是引擎提供的逻辑元素词,适合于构建复杂的sql语句。其中有的已经在上面的场景中用到了,不难理解。不支持迭代和if形式的语句(而mybatis是支持的)。
@dynamic动态创建。表示其中的内容是否要包含,完全靠传入的参数决定。属性有prepend,其值即为在动态内容前面添加的内容
@isNotNull参数值是否不为空。属性有prepend和property,表示如果property对应的值存在,那么就将isNotNull元素体内容加入到 sql,并在前面增加prepend的值,元素体中的##或$$里的内容替换为property在参数中对应的值。
@isNull 参数值是否为空,与isNotNull相反。
@isEqual参数值是否等于指定值。 属性有prepend、property和 compareValue,即判断参数中property所对应的值是否为compareValue的值,如果是,纳入元素体的内容,替换##或$$中的值。
@isNotEqual是否不相等。 与isEqual正相反。属性有prepend、 property、compareValue
@isLessThan参数值是否小于指定值。属性有prepend、 property、 compareValue,如果property在参数中的值小于compareValue的值,纳入元素体的内容,替换##或$$中的值。
@isGreaterEqual是否大于等于。和isLessThan相反。属性有prepend、 property、compareValue
@isBetween 介于两个值之间。属性有prepend、 property、compareValue1、compareValue2,即满足compareValue1<=property并<=compareValue2条件时,纳入元素体的内容,替换##或$$中的值。
@isNotBetween不在范围内,与isBetween相反。即property<compareValue1和property>compareValue2时,纳入元素体的内容,替换##或$$中的值。
@isStartWith参数字符串以指定值开头。属性有prepend、 property、 compareValue
@isNotStartWith与isStartWith相反。属性有prepend、 property、compareValue
@isEndWith字符串以指定值结尾。属性有prepend、 property、 compareValue
@isNotEndWith与isEndWith相反。属性有prepend、 property、compareValue
@isLengthEqual字符串长度等于指定的整数值。属性有prepend、 property、 compareValue
@isLengthNotEqual字符串长度不等于指定的整数值。属性有prepend、 property、 compareValue
@isContains 参数值包含指定的字符串。属性有prepend、 property、compareValue
@isNotContains参数值不包含指定的字符串。属性有prepend、 property、 compareValue
@<![CDATA[]]>所有xml的通行作法,表示元数据,这里主要是在sql中含有大于号>或小于号<时使用。
@##和$$的区别,前者会根据参数的类型替换##的内容,即如果是字符串,就替换为'xx';数值型的,替换为xx;日期型的,替换为与特定数据库相应的格式,等等。 而后者则不作类型判断,直接作简单的原样替换。
1. 调用存储过程
引擎对存储过程的调用也是很方便的,下面针对几种数据库列出几个例子。不同的库存储过程调用方法是一样的,不同的只是各种过程所需要的参数类型有所区别。
A. oracle过程
假如有oracle的过程1,需要获得结果集:
CREATE OR REPLACE PROCEDURE sp_oracle1(
result OUT SYS_REFCURSOR
) AS
BEGIN
OPEN result FOR SELECT * from user;
end ;
调用:
int[] out=new int[]{oracle.jdbc.OracleTypes.CURSOR};//定义传出参数的类型
Map map=DataCenter.getByProcedure("sp_oracle1",null,out);
List records=map.get(“result”);// result是存储过程的传出参数的名称
Oracle过程2,包含两个传入参数,两个结果集传出参数:
CREATE OR REPLACE PROCEDURE sp_oracle2(
in_name invarchar2, --传入参数
in_age inint, --传入参数
res1 OUT SYS_REFCURSOR,--传出结果
res2 OUT SYS_REFCURSOR --传出结果
) AS
BEGIN
OPEN res1 FOR SELECT * from user where name=in_name;
OPEN res2 FOR SELECT * from user where age>in_age;
end ;
调用:
int[] out=new int[]{oracle.jdbc.OracleTypes.CURSOR,oracle.jdbc.OracleTypes.CURSOR};
Mapobj=DataCenter.getByProcedure("sp_oracle2",new Object[]{"zhang",30},out);
List records1= (List<Map<String,Object>>)obj.get("res1");//第一个结果
List records2= (List<Map<String,Object>>)obj.get("res2");//第二个结果
B. db2过程
假如存储过程,既有in参数,也有out参数,还有inout参数:
CREATE PROCEDURE sp_db2(
in nm_in1 VARCHAR(50),
in nm_in2 varchar(50),
out uid integer,
inout uname VARCHAR(50)
)
RESULT SETS 1
LANGUAGE SQL
BEGIN
DECLARE C1 CURSOR WITH RETURN FOR
SELECT * FROM user where name like nm_in1||'%';
OPEN C1;
SELECT id into uid FROM user where name = nm_in2;
select name into uname FROM user where name =uname;
END
调用:
Object[] in=newObject[]{"zhang","liu"};
int[] out=newint[]{Types.INTEGER};
Object[][]inout=new Object[][]{{"wang"},{Types.VARCHAR}};
Mapobj=DataCenter.getByProcedure("sp_db2",in,out,inout);
List records=(List<Map<String,Object>>)obj.get(2);
Int id=obj.get("uid");
Stringname=obj.get("uname");
C. mysql过程
假如有过程proc_name,根据传入的参数决定查询哪个表:
CREATE PROCEDURE proc_name(in parameter integer)
begin
if parameter=0 then
select * from student ;
else
select * from test ;
end if;
end
调用:
Mapres=DataCenter.getByProcedure("proc_name",new Object[]{0});
List<Map<String, Object>> result=(List<Map<String,Object>>) res.get(1);
调用过程的方法中参数的类型只有两种,一种是int数组,一种是Object数组,
前者定义参数的数据类型,后者定义参数的具体值。
在返回的结果map中,key是存储过程中传入参数或传入传出参数的名称,或者是结果集的顺序编号,编号从1开始。如果存储过程无任何参数,但包含结果集,使用按顺序的方式获取所需结果集。如果存储过程没有任何传入传出参数,直接调用即可:
DataCenter.getByProcedure("SP_DBTEST");
2. 直接使用原生SQL
在项目开发过程中,有时可能已经有现成的sql语句了;或者业务稍显复杂,单表操作不好实现,但又不想为此单独建一个sql.xml配置文件;或者有的操作根本不涉及到库表,例如,postgreSQL或mysql获取md5的值,select md5(‘abc’),这种情况下,最方便的操作就是调用:getBySql(sql)。
//求abc的md5值(不是每种库都支持该函数)
Object object = DataCenter.getBySql("select md5('abc') val");
Map map=(Map) ((List)object).get(0);
String val=( String) map.get(“val”);//获取结果
Object object = DataCenter.getBySql("select count(*) ct from student");
Map map=(Map) ((List)object).get(0);
int count=(Integer) map.get("ct");//获取结果数
Object object = DataCenter.getBySql("select * from student");
List list=(List)object;//记录集
Object object = DataCenter.getBySql("delete from student where sid=1");
int count=(Integer)object;//删除的记录数
Object object = DataCenter.getBySql("drop table test_tab");//删除test_tab表
boolean flag=(Boolean)object;//返回false,表示ddl操作
上面传递的都是简单的语句,但可以是任意的复杂sql,至于返回什么样的结果,完全是基于sql语句来的,可根据需要转型为实际的结果类型。
引擎还提供了一个可以传递参数值的方法:
public static Object getBySql(String sql,Object[] paramValues)
与上面的区别在于,这里面的sql不是完整sql,是含有问号?占位符的,后边的
paramValues传递占位符对应的值。
String sql=”select * from student where name=? and age>?”;
Object object = DataCenter.getBySql(sql,new Object[]{“张三”,20});//注意20是没引号的
List list=(List)object;//记录集
3. 操作视图
如果库中含有视图view,与针对表的操作完全一样,传递视图名即可。至于能否向视图里插入数据等操作,完全与具体的库相关。
- java数据引擎(五):详细使用
- java数据引擎(二):详细使用
- java数据引擎(三):详细使用
- java数据引擎(四):详细使用
- [Drools]JAVA规则引擎 -- Drools 详细说明
- java数据引擎(七):总结
- java使用js引擎例子
- java使用js引擎例子
- java数据引擎(一):引擎渊源和快速入门
- java数据引擎(六):高级主题
- java数据引擎(八):应用一
- java数据引擎(九):应用二
- java数据引擎(十):应用三
- java数据引擎(十一):应用四
- 游戏引擎Andengine总结(五):TexturePacker的使用
- Pig数据分析引擎 二 使用PigLatin语句分析数据
- Java创建和解析Json数据方法(五)——Google Gson包的使用
- [Sqlite]-->Java使用jdbc连接Sqlite数据库进行各种数据操作的详细过程
- java初级
- PythonChallenge第5题
- African demand of film faced plywood increasing
- mappingResources、mappingLocations、mappingDirectoryLocations、mappingJarLocations
- 源码推荐:多图无缝滚动控件,多视图控制器间切换
- java数据引擎(五):详细使用
- 第三章第17题
- 我的IO漫谈
- 链表的基本操作
- CTLChart控件引用头文件CTLXYChart.h
- java BigDecimal
- HDU--2203(kmp,模板题)
- 我的Coursera历程
- 【转载&收藏】前端必读:浏览器内部工作原理