人无信不立/2008-04-26 22:30
永春阁
专注于技术,切不可沉湎于技术
博客园
社区
首页
新随笔
联系
管理
订阅
随笔- 226 文章- 20 评论- 1276
IBatis.Net学习笔记五--常用的查询方式
在项目开发过程中,查询占了很大的一个比重,一个框架的好坏也很多程度上取决于查询的灵活性和效率。
在IBatis.Net中提供了方便的数据库查询方式。
在Dao代码部分主要有两种方式:
1、查询结果为一个对象:
ISqlMapper sqlMap
=
sqlMapDaoSession.SqlMap;
return
(Account) sqlMap.QueryForObject(
"
GetAccountViaColumnName
"
, accountID);
2、查询结果为一个列表:
ISqlMapper sqlMap
=
sqlMapDaoSession.SqlMap;
return
(ArrayList)sqlMap.QueryForList(
"
GetAccountAsHashtableResultClass
"
,
1
);
这两种方法同时都提供了面向泛型的重载方法。这两个方法的第一个参数对应配置文件中的select id,第二个参数表示传入查询的条件
配置文件的写法:
在IBatis.Net中提供了多种查询配置的写法,我这里列出几种比较常用的方式:
1、获得一张表的所有数据
<
select id
=
"
GetAllAccountsAsHashMapViaResultMap
"
resultMap
=
"
account-hashtable-result
"
>
select
*
from Accounts
order by Account_ID
</
select
>
这是最简单的方式,其中resultMap是返回查询结果的形式,需要另外配置:
<
resultMap id
=
"
account-hashtable-result
"
class
=
"
Hashtable
"
>
<
result property
=
"
Id
"
column
=
"
Account_ID
"
/>
<
result property
=
"
FirstName
"
column
=
"
Account_FirstName
"
/>
<
result property
=
"
LastName
"
column
=
"
Account_LastName
"
/>
<
result property
=
"
EmailAddress
"
column
=
"
Account_Email
"
/>
</
resultMap
>
表示:得到的结果的每一条记录都映射成一个Hashtable,这个Hashtable中包含四个Key(Id,FirstName......)
2、根据条件查询(简单方式):
<
select id
=
"
GetAccountViaColumnIndex
"
parameterClass
=
"
int
"
resultMap
=
"
indexed-account-result
"
>
select
Account_ID,
Account_FirstName,
Account_LastName,
Account_Email
from Accounts
where Account_ID
=
#value#
</
select
>
只有一个条件,传入参数的类型是int型,拼写sql时直接用 #value#就可以了
3、根据条件查询(较复杂方式):
<
select id
=
"
GetAccountsDynamic
"
resultMap
=
"
account-result
"
parameterClass
=
"
Hashtable
"
>
select top $MaximumAllowed$
*
from Accounts
<
dynamic prepend
=
"
where
"
>
<
isParameterPresent
>
<
isNotEmpty prepend
=
"
and
"
property
=
"
FirstName
"
>
Account_FirstName LIKE
'
%$FirstName$%
'
</
isNotEmpty
>
<
isNotEmpty prepend
=
"
and
"
property
=
"
LastName
"
>
Account_LastName LIKE
'
%$LastName$%
'
</
isNotEmpty
>
<
isNotEmpty prepend
=
"
and
"
property
=
"
EmailAddress
"
>
Account_Email LIKE
'
%$EmailAddress$%
'
</
isNotEmpty
>
</
isParameterPresent
>
</
dynamic
>
order by Account_LastName
</
select
>
传入参数是一个Hashtable,
MaximumAllowed
等表示的是Hashtable里的key值,用$$包含起来。
并且查询时可以根据条件是否为空动态拼写sql语句
PS:输入参数同样可以使用Account类,注意对应的键要和类中的属性名一致(大小写也要一样)
4、多表查询
多表查询时返回参数有三种方式,一种是新建一个类,在这个类中包含这多个表的所有属性,还有一种就是直接返回Hastable就可以了:
<
select id
=
"
GetAccountAsHashtableResultClass
"
resultClass
=
"
HashMap
"
>
select
a.
*
,b.
*
from a,b
where a.Account_ID
=
b.Account_ID
</
select
>
PS:这里的HashMap实际上就是Hashtable
第三种方式是使用IBatis中的复杂属性(
感谢
Anders Cui
的提醒
)
比如现在有两张表Account和Degree,使用Account_ID关联,那么需要在原有的基础上修改:
1、修改Account实体类,加入一个属性:
private
Degree _degree;
public
Degree Degree
{
get
{
return
_degree;
}
set
{
_degree
=
value;
}
}
这样是一个1:1的关系,也可以加入IList DegreeList的属性,这样查询的结果就是一个1:n的关系
2、修改配置文件:
在
resultMaps
节加入:
<
resultMap id
=
"
comresult
"
class
=
"
Account
"
>
<
result property
=
"
Id
"
column
=
"
Account_ID
"
/>
<
result property
=
"
FirstName
"
column
=
"
Account_FirstName
"
/>
<
result property
=
"
LastName
"
column
=
"
Account_LastName
"
/>
<
result property
=
"
EmailAddress
"
column
=
"
Account_Email
"
nullValue
=
"
no_email@provided.com
"
/>
<
result property
=
"
Degree
"
column
=
"
Account_ID=Account_ID
"
select
=
"
degreeretrive
"
/>
</
resultMap
>
对于Degree属性,还可以加入
lazyLoad
=true 延迟加载,优化性能(也就是开始时并没有实际查询数据库,当用到属性Degree时,才实际的查询相应的数据)
在
statements
节加入:
<
statement id
=
"
degreeretrive
"
parameterClass
=
"
Hashtable
"
resultClass
=
"
Degree
"
>
select
*
from Degree
where Account_id
=
#Account_ID#
</
statement
>
<
select id
=
"
GetComTables
"
resultMap
=
"
comresult
"
>
select
*
from Accounts
order by Account_ID
</
select
>
这样可以正确的查询出结果,符合OO,但是也有两个小问题:
1、比较麻烦,不够灵活
2、性能受影响:
这种方式其实和Hibernet比较类似了,查询时首先执行
select * from Accounts order by Account_ID
然后根据这条语句的结果,比如有100条记录,那就要执行100次以下的语句:
select * from Degree where Account_id = @param0
关于输入输出:
从上面可以看到输入时可以使用:
parameterClass和
parameterMap,输出时可以使用:
resultClass和
resultMap
对于
resultMap和
parameterMap
我们需要另外进行配置(如上所示)
对于
parameterClass和
resultClass
,如果是C#固有类型可以直接使用,如果是我们自定义类可以在SqlMap.config中先统一声明一下:
<
alias
>
<
typeAlias alias
=
"
Account
"
type
=
"
GSpring.Domain.Account
"
/>
</
alias
>
posted @ 2007-08-21 11:18
永春
阅读(3190)
评论(25)
编辑
收藏
所属分类:
iBATIS.NET
发表评论
回复
引用
查看
#1楼
2007-08-21 13:33 |
Anders Cui
多表查询时
感觉你说的两种方法有时不太好
如果新建一个类
那么情况复杂时,需要建的类就不止一个了;
如果使用Hashtable
那么就弃domain object于不顾了.
建议还是用复杂属性的方式
比较符合OO
可以考虑resultMapping或select两个选项
回复
引用
#2楼
2007-08-21 15:44 |
shrpcn [未注册用户]
ibatis 有一个版本分支,支持DataTable返回.
还有resultMap 不是必需的attribute,
可以让select 列别名与实体属性一致,省掉编写的resultMap Node.
回复
引用
查看
#3楼
[
楼主
]2007-08-21 16:16 |
GSpring
@shrpcn
你说的就是使用resultClass的方式吧。
回复
引用
查看
#4楼
[
楼主
]2007-08-21 17:20 |
GSpring
@Anders Cui
谢谢你的建议,我已经加到文章中去了。
不过这种方式还是有点小问题的
回复
引用
查看
#5楼
2007-08-21 20:18 |
Anders Cui
@GSpring
:)
看了你说的两个问题
根据你举的例子
对resultMap可以使用extends属性
这样只要我们写好了针对Account和Degree的单表操作
要做的额外工作也不多
关于性能问题,我觉得也可以解决
我们很少需要每次加载100条
我觉得不管怎样
总是应该只加载必要的数据
如果并不需要一次就加载两个表的数据
可以使用lazyLoad
如果确实需要一次就加载两个表的数据
可以用一条SQL来加载所需要的数据
这样就不用执行很多次查询了
回复
引用
#6楼
2007-08-21 23:26 |
coollzh [未注册用户]
有了DLinq看看IBatis.net会朝那个方向发展,获取会出现IBatisLinq:)
回复
引用
#7楼
2007-08-22 08:11 |
tc [未注册用户]
楼主应该学习新版本的泛型返回查询 性能会更高
Isqlmap.QueryForObject<type>
Isqlmap.QueryForList<type>
回复
引用
#8楼
2007-08-22 08:36 |
GSpring [未注册用户]
@tc
泛型方法的确不错-_-,我在文中也提及到了
回复
引用
查看
#9楼
[
楼主
]2007-08-22 08:38 |
GSpring
@coollzh
DLinq我还没有用过,有时间的话看看
回复
引用
查看
#10楼
[
楼主
]2007-08-22 08:46 |
GSpring
@Anders Cui
谢谢:)
不过我想问一下:用一条SQL来加载所需要的多张表的数据 好像只能使用前两种方法了吧?
回复
引用
查看
#11楼
[
楼主
]2007-08-22 09:40 |
GSpring
@Anders Cui
我好像找到了一种方法:),待会我再把它写出来
具体参见:
IBatis.Net学习笔记六--再谈查询
回复
引用
#12楼
2007-09-03 11:44 |
老袁 [未注册用户]
救救我吧,大哥,把一个列映射到一个对象怎么搞啊?
比如,我有个Person表,里面有很多描述属性的Columns,我想在Person对象里建一个Properties的Hash表,每个Property都是一个对象,它读取对应列的数据并实例化。
class Person
{
long id;
string name;
IList<Property> properties;
}
<resultmap id = "GetPerson" class = "Person">
<result property = "ID" column = "id">
<result property = "Name" column = "name">
<result property = "Properties" ??????
</resultMap>
<select id = "GetPersonByID" parameterClass="int" resultMap="GetPerson">
select id,name,weight,height,address,email,money from person
where id = #value#
</select>
回复
引用
#13楼
2007-09-03 16:36 |
GSpring [未注册用户]
@老袁
不是很明白你的意思
不过你可以把每个属性都作为Person中的一个字段就可以了呀
回复
引用
#14楼
2007-09-03 23:59 |
老袁-- 邮件 yuanhaipeng@gmail.com [未注册用户]
Person类有很多的属性(100多个),我建立一个通用的Property类,每个属性都是Property类的实例, 然后建立一个属性集合(Hashtable)把这些属性放进去。iBatis如何实现?
c#示意代码
Property 身高 = new Property("150","int");
Property 血型 = new Property("c","string");
HashTable properties = new HashTable();
properties.Add("身高",身高);
properties.Add("血型",血型);
Person person = new Person(1,"小王");
person.Properties = properties;
数据库表(Person)
ID Name Height Weight BloodType ....
1 小王 150 60 c
急啊,兄弟,指望你这个专家帮我解决一下!
public class Person
{
public int ID {}
public string Name{}
public HashTable Properties;
//other methods
}
public class Property
{
public string DataValue{}
public string DataType{}
//other properties and methods
}
<resultMap id = "ResultWeightProperty" class = "Property">
<result property = "DataValue" column = "Weight"/>
<!--no column-->
<result property = "DataType" value = "int"/>
<resultMap>
<resultMap id = "PersonProperties" class = "HashTable">
<result property ="weight" resultMapping = "ResultWeightProperty"/>
<result property ="height" resultMapping = "ResultHeightProperty"/>
</resultMap>
<resultMap id = "ResultPerson" class = "Person">
<result property = "ID" column = "id"/>
<result property = "Name" column = "name"/>
<result property = "Properties" resultMapping= "PersonProperties"/>
</resultMap>
<select id = "GetPersonProperties" parameterClass = "int" resultMap = "ResultPerson">
select id,name,weight,height,haircolor,.... from person where person_id = #value#
</select>
回复
引用
查看
#15楼
[
楼主
]2007-09-04 14:31 |
GSpring
@老袁-- 邮件 yuanhaipeng@gmail.com
我又写了一个
IBatis.Net学习笔记八--把字段映射成一个自定义对象
,和你说的有点类似,你可以参考一下,看能不能实现你的需求
回复
引用
#16楼
2007-09-04 14:47 |
老袁 [未注册用户]
非常感激博主认真解答我的问题(我已经看了你的iBatis笔记八),我也在尝试使用CustomizedTypeHandler,但是我的根本问题还是有点阻碍。因为这样还是要在Class Person里定义Weight,Height等属性,有多少个定义多少个,但我的起始目的是只在Person对象里建立一个名为Properties的属性。如下,
pubilc class Person
{
public int ID {}
public string Name{}
public HashTable Properties;
}
Person只有三个属性!
谢了!
回复
引用
查看
#17楼
[
楼主
]2007-09-04 14:56 |
GSpring
@老袁
你也可以试试:
<result property="Properties" resultMapping="Account.GetProperties"/>
<resultMap id="GetProperties" class="Hashtable" >
<result property="LastName1" column="Account_LastName" typeHandler="GSpring.Common.PropertyTypeHandler"/>
<result property="EmailAddress1" column="Account_Email" typeHandler="GSpring.Common.PropertyTypeHandler"/>
</resultMap>
不过和你的需求可能还是有点差别,就是不好设置DataType的值了。
另:我也是在学习,谈不上什么高手-_-
回复
引用
#18楼
2007-09-04 19:42 |
老袁 [未注册用户]
实现上还是有些问题啊,我的配置如下。。。
<resultMap id ="WeightObservationMapping" class ="Property">
<result column ="weight" property ="DataValue"/>
<!--有些列并不存在(需要给Property类的属性给常量值),问题?-->
<result property = "DataType" value="int"/>
</resultMap>
<resultMap id ="HeightObservationMapping" class ="Property">
<result column ="height" property ="HeightObservationMapping"/>
<result column ="weight" property ="WeightObservationMapping"/>
</resultMap>
<resultMap id ="PProperties" class ="HashTable">
<result column ="weight" ResultMapping ="DataValue"/>
<result property = "DataType" value="int"/>
</resultMap>
<!--Person-->
<resultMap id ="ResultPerson" class="Person">
<result property ="Id" column="int_id"/>
<result property ="Name" column="name"/>
<result property ="Properties" ResultMapping="PProperties"/>
</resultMap>
<!--定义语句-->
<statements>
<!--选择语句-->
<select id ="GetPersonByName" parameterClass="string" cacheModel ="NECache" resultMap="ResultPerson">
select int_id,Name,weight,height from
T_PERSON where (Name = #value#)
</select>
回复
引用
#19楼
2007-09-04 20:06 |
老袁 [未注册用户]
实现上还是有些问题啊,我的配置如下。。。
<resultMap id ="WeightObservationMapping" class ="Property">
<result column ="weight" property ="DataValue"/>
<!--有些列并不存在(需要给Property类的属性给常量值),问题?-->
<result property = "DataType" value="int"/>
</resultMap>
<resultMap id ="HeightObservationMapping" class ="Property">
<result column ="height" property ="DataValue"/>
<result column ="weight" value ="int"/>
</resultMap>
<resultMap id ="PProperties" class ="HashTable">
<result column ="weight" ResultMapping ="WeightObservationMapping"/>
<result column ="height" ResultMapping ="HeightObservationMapping"/>
</resultMap>
<!--Person-->
<resultMap id ="ResultPerson" class="Person">
<result property ="Id" column="int_id"/>
<result property ="Name" column="name"/>
<result property ="Properties" ResultMapping="PProperties"/>
</resultMap>
<!--定义语句-->
<statements>
<!--选择语句-->
<select id ="GetPersonByName" parameterClass="string" cacheModel ="NECache" resultMap="ResultPerson">
select int_id,Name,weight,height from
T_PERSON where (Name = #value#)
</select>
回复
引用
#20楼
2007-09-05 09:50 |
GSpring [未注册用户]
@老袁
对于有些列并不存在的情况,我也不知道怎么赋值,在笔记八中我是在代码中写死的。
我建议这种值还是在代码中写吧。查询之后,遍历Hashtable,赋值。
毕竟IBatis主要是用来和数据库交互的,和业务有关的部分不好写在配置文件中的。
不过总感觉你的需求好像有点奇特-_-
回复
引用
#21楼
2007-09-05 12:52 |
老袁 [未注册用户]
呵,没有办法,我只好把这些任务全交给TypeHandler,把TypeHander作为一个PropertyFactory(远离了iBatis的Type<-->DBType的本意)。。。
我只是想在外面配置Property的DataType,比如Int,String
我的需求应该也很普遍,确实是因为属性太多的缘故,我采用的是Martin Fowler分析模式的Observation模式和Validator模式
回复
引用
#22楼
2007-09-05 12:58 |
老袁 [未注册用户]
因为要把TypeHandler作为工厂,因此就需要一些自定义的参数,我不想修改iBatis的<result>添加新的Attribute,只好把这些参数放在一个DataDictinary
里,然后通过propertyName去匹配,算是勉强解决了问题。。。
iBatis能不能支持把Column直接映射到Object,而不是通过行记录呢?
回复
引用
查看
#23楼
2007-09-05 14:49 |
GSpring
@老袁
好像不行的,Column肯定是作为一行记录的一个Column来映射的
回复
引用
#24楼
2007-09-05 17:14 |
老袁 [未注册用户]
是啊,我在看iBatis的文档,但这些文档并不会涉及iBatis的设计哲学和体系原理,要理解这些,还得看代码,才能点透。。。好在还有代码,本来我们自己是写了个O/R Framework的,我考虑到维护代价,才改成iBatis.Net。。。可以的话,我可以公布这个O/R Framework的代码,让大家有兴趣一起提升提升。。。
新用户注册
刷新评论列表
标题
姓名
主页
Email
(博主才能看到)
验证码
*
看不清,换一张
[
登录
][
注册
]
内容(请不要发表任何与政治相关的内容)
网站首页
新闻频道
社区
小组
博问
网摘
闪存
找找看
Remember Me?
登录
使用高级评论
新用户注册
返回页首
恢复上次提交
[使用Ctrl+Enter键可以直接提交]
该文被作者在 2007-08-22 13:34 编辑过
相关文章:
使用Visual Studio2005入门.Net2.0系列视频教程
Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇
相关链接:
所属分类的其他文章:
IBatis.Net学习笔记十三:在IBatis.Net中调用存储过程
IBatis.Net学习笔记系列文章
IBatis.Net学习笔记十二:发现一个好用的IBatis.Net生成工具
IBatis.Net学习笔记十一:Castle.DynamicProxy的使用
IBatis.Net学习笔记十--数据库连接处理
IBatis.Net学习笔记九--动态选择Dao的设计分析
Ibatis.Net和Ibatis使用注意点及异同点(不断更新)
IBatis.Net学习笔记八--把字段映射成一个自定义对象
IBatis.Net学习笔记七--日志处理
IBatis.Net学习笔记六--再谈查询
最新IT新闻:
Google向Wine贡献更多代码
苹果创始人Steve Wozniak称iPod将被淘汰
福布斯:硅谷日子将更难过 谁下一个倒下
微软老矣 尚能赚否?
YouTube探索新赢利模式 开始售音乐、视频游戏
公告
本Blog版权均为本人所有,欢迎任何媒体和网站转载本人博客的内容。
本Blog的内容按原样提供,本人不提供任何形式的担保。
转载请注明出处
我的MVP配置
自2007年3月8日:
系列文章
1、
Sharepoint2007对象模型系列
2、
C#强化系列文章
3、
MOSS SDK学习系列
4、
IBatis.Net学习笔记系列
5、
MonoRail学习笔记系列
<
2007年8月
>
日
一
二
三
四
五
六
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
与我联系
发短消息
搜索
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
我的新闻
最新评论
我的标签
留言簿
给我留言
查看留言
我参加的小组
Debug 探索团队小组
写书译书小组
博客园精华集出版小组
iBATIS.NET
MonoRail
我参与的团队
SharePoint团队(0/744)
Ajax&Atlas技术团队(0/1138)
南京.net俱乐部(0/429)
ASP.NET AJAX (Atlas)学习(0/1353)
MVP(微软最有价值专家)团队(0/637)
Debug 探索团队(0/53)
博客园精华集出版(0/45)
随笔分类
.Net(49)
(rss)
AJax(3)
(rss)
C++/VC学习(2)
(rss)
iBATIS.NET(15)
(rss)
Java(6)
(rss)
MonoRail(25)
(rss)
OS Shell(5)
(rss)
SharePoint(42)
(rss)
Windows Server(1)
(rss)
XHTML/CSS/Script(6)
(rss)
企业开发(2)
(rss)
数据库(21)
(rss)
外语(1)
(rss)
项目管理(7)
(rss)
娱乐/杂记/修养(49)
(rss)
随笔档案
2008年9月 (1)
2008年8月 (3)
2008年7月 (7)
2008年6月 (1)
2008年5月 (2)
2008年4月 (12)
2008年3月 (14)
2008年2月 (3)
2008年1月 (14)
2007年12月 (17)
2007年11月 (21)
2007年10月 (31)
2007年9月 (13)
2007年8月 (25)
2007年7月 (10)
2007年6月 (1)
2007年5月 (2)
2007年4月 (10)
2007年3月 (15)
2007年2月 (7)
2007年1月 (1)
2006年12月 (3)
2006年11月 (21)
2006年10月 (5)
2006年8月 (2)
SharePoint学习
Codeplex Sharepoint
jianyi @ cnblogs
Kaneboy's Blog
Patrick Tisseghem's Blog
管理相关
下载_中计在线
中国管理之家
开源社区
C#开源资源大全
Java开源大全
SourceForge主页
门户网站
南京程序员俱乐部
积分与排名
积分 - 300344
排名 - 98
最新评论
1. re: C#强化系列文章
太牛了,我找了好久的资料呀,爱死你了 (luoxp)
2. re: MonoRail学习笔记十:Controller和Url的对应关系
感谢,一直对这方面不熟悉。 MonoRail果然是个好东西!! 特别对于刚从asp转到。net的人来说简直就是回归自然!! 网站建设... (benfeng)
3. re: MonoRail学习笔记十一:页面控件的填充和验证
@Ariel Y.
Brail 是什么东西?
API做得好吗?
4. re: 为什么要使用MonoRail?
不知道是用MonoRail好还是用ProMesh好!
希望给点建议。
网站建设
(benfeng)
5. re: IBatis.Net学习笔记十--数据库连接处理
你好,我现在碰上一个问题
我现在有两个数据库,对应有两个连接,请问一下,要如何处理呢?谢谢 (Scrofield)
阅读排行榜
1. 这样的面试题你会吗?(4768)
2. 易经杂说—南怀瑾(4397)
3. Asp.Net Forms验证(自定义、角色提供程序、单点登录)(4196)
4. 年终个人总结:我这五年(4016)
5. 为什么要使用MonoRail?(3929)