在ibatis中使用一对多的问题,搜了很久没有解决,望高手告知

siyue 2008-07-31 07:54:02
目前我们有一项目使用ibatis,在解决一对多问题时采用了groupBy的方法,例子如下:
但问题是由于使用了left join,当CATEGORY 中有一条记录在PRODUCT没有关联记录时必须为productResult中的属性设置nullValue,并且productList中会有一个对象,对象里是空值。我希望出现这种情况时,productList就为空。或者size为0,这样如何处理?谢谢!

<sqlMap namespace="ProductCategory">
<resultMap id=”categoryResult” class=”com.ibatis.example.Category” groupBy=”id”>
<result property=”id” column=”CAT_ID”/>
<result property=”description” column=”CAT_DESCRIPTION”/>
<result property=”productList” resultMap=”ProductCategory.productResult”/>
</resultMap>
<resultMap id=”productResult” class=”com.ibatis.example.Product”>
<result property=”id” column=”PRD_ID”/>
<result property=”description” column=”PRD_DESCRIPTION”/>
</resultMap>
<select id=”getCategory” parameterClass=”int” resultMap=”categoryResult”>
select C.CAT_ID, C.CAT_DESCRIPTION, P.PRD_ID, P.PRD_DESCRIPTION
from CATEGORY C
left join PRODUCT P
on C.CAT_ID = P.PRD_CAT_ID
where CAT_ID = #value#
</select>
</sqlMap>
...全文
223 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
南南北北 2008-08-02
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 Landor2004 的回复:]
引用 17 楼 Landor2004 的回复:
楼上的,你的这种写法,虽然可以实现,但是完全不可取,
如果一个Catelog包含n多的CatelogAttribute的时候,会执行n+1条sql语句
导致到n+1的问题,严重影响性能!

更正是一个Catelog,包含多个Product的时候,呵呵
[/Quote]

的确存在这个问题,特别是Product数量多的时候.

<select id="findCatelogById" parameterClass="int"
resultMap="catelogResult">
select id as id, name as name from CATELOG where id=#id#
</select>
我比较喜欢在findCatelogById方法中,调用findProductListByCatelogId,然后set给Catelog的productList属性.

个人习惯问题,我不喜欢写复杂的sql,如果必须要写的话,就建个视图吧.
siyue 2008-08-01
  • 打赏
  • 举报
回复
谢谢各位了,问题现在又没有了,好像也没有改,真是糊涂了。
还有一个问题,我数据库用的是mysql,在使用上面方法时使用了limit 0, 20。他们同时使用是有问题的,因为我想限制的是Catalog的记录,这个问题大家有什么好的解决方法?
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
或者你在dao里面手工的判断修改一下吧
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 siyue 的回复:]
引用 9 楼 Landor2004 的回复:
如果不加nullValue的话就报错了
[/Quote]
这个不会吧,可以识别成0,不过上面我说的方法似乎不行,呵呵,应为ibatis是先new了一个集合productList,然后ibatis再给再赋值的,如果加上那个语句的话,每次new出来就被我赋值成null了

这个可能要修改ibatis的源码了,不过不知道你用来做什么,这个可能也没什么太大影响,帮你up了
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 Landor2004 的回复:]
楼上的,你的这种写法,虽然可以实现,但是完全不可取,
如果一个Catelog包含n多的CatelogAttribute的时候,会执行n+1条sql语句
导致到n+1的问题,严重影响性能!
[/Quote]
更正是一个Catelog,包含多个Product的时候,呵呵
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
楼上的,你的这种写法,虽然可以实现,但是完全不可取,
如果一个Catelog包含n多的CatelogAttribute的时候,会执行n+1条sql语句
导致到n+1的问题,严重影响性能!
siyue 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 Landor2004 的回复:]
看你的查询语句得到的查询结果,你用left join的话,右侧没有对应的肯定是null,而你设置nullValue="0",结果会转化为0
那返回的值里面肯定包括0这个product的ID,你既然不想要结果,为何还要nullValue="0",这岂不是自相矛盾,去掉nullValue="0"
[/Quote]

如果不加nullValue的话就报错了
siyue 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 norwolfli 的回复:]
你为什么要使用left join呢?
<select id=”getCategory” parameterClass=”int” resultMap=”categoryResult”>
select C.CAT_ID, C.CAT_DESCRIPTION
from CATEGORY where CAT_ID = #value#
</select>

这样就可以了,因为有 <result property=”productList” resultMap=”ProductCategory.productResult“/>
这句话,所以你得到的Category对象中的productList属性会自动添充。
[/Quote]


谢谢回复,这样好像不行的吧。这样category和product的关系怎样关联起来呢?
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 siyue 的回复:]
谢谢你的回复。不过使用了我上面写的方法后,必须在“productResult”中添加nullValue,这样得到的结果是无论如何在productList至少会有一个对象,而这个对象的数据就是product.id = 0,product.description=""
所以你的解决方案不管用。

<resultMap id=”productResult” class=”com.ibatis.example.Product”>
<result property=”id” column=”PRD_ID”nullValue="0"/>
<result property=”description” column=”PRD…
[/Quote]

看你的查询语句得到的查询结果,你用left join的话,右侧没有对应的肯定是null,而你设置nullValue="0",结果会转化为0
那返回的值里面肯定包括0这个product的ID,你既然不想要结果,为何还要nullValue="0",这岂不是自相矛盾,去掉nullValue="0"
siyue 2008-08-01
  • 打赏
  • 举报
回复
谢谢你的回复。不过使用了我上面写的方法后,必须在“productResult”中添加nullValue,这样得到的结果是无论如何在productList至少会有一个对象,而这个对象的数据就是product.id = 0,product.description=""
所以你的解决方案不管用。

<resultMap id=”productResult” class=”com.ibatis.example.Product”>
<result property=”id” column=”PRD_ID”nullValue="0"/>
<result property=”description” column=”PRD_DESCRIPTION”nullValue="" />
</resultMap>
南南北北 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用楼主 siyue 的帖子:]
<sqlMap namespace="ProductCategory">
<resultMap id=”categoryResult” class=”com.ibatis.example.Category” groupBy=”id”>
<result property=”id” column=”CAT_ID”/>
<result property=”description” column=”CAT_DESCRIPTION”/>
<result property=”productList” resultMap=”ProductCategory.productResult”/>
</resultMap>
<resultMap id=”productResult” class=”com.ibatis.example.Product”>
<result property=”id” column=”PRD_ID”/>
<result property=”description” column=”PRD_DESCRIPTION”/>
</resultMap>
<select id=”getCategory” parameterClass=”int” resultMap=”categoryResult”>
select C.CAT_ID, C.CAT_DESCRIPTION, P.PRD_ID, P.PRD_DESCRIPTION
from CATEGORY C
left join PRODUCT P
on C.CAT_ID = P.PRD_CAT_ID
where CAT_ID = #value#
</select>
</sqlMap>
[/Quote]

你为什么要使用left join呢?
<select id=”getCategory” parameterClass=”int” resultMap=”categoryResult”>
select C.CAT_ID, C.CAT_DESCRIPTION
from CATEGORY where CAT_ID = #value#
</select>

这样就可以了,因为有<result property=”productList” resultMap=”ProductCategory.productResult“/>
这句话,所以你得到的Category对象中的productList属性会自动添充。


Landor2004 2008-08-01
  • 打赏
  • 举报
回复
这个问题是ibatis的内部实现就是这样的,不过如果想得到你的效果的话很简单

只需在Category类中的setProductList方法中写一个转换即可,如下
	public void setProductList(Collection<Product> productList) {
if(productList!=null && productList.isEmpty())
productList= null;
this.productList= productList;
}
siyue 2008-08-01
  • 打赏
  • 举报
回复
没有人碰到过?
Landor2004 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 java2000_net_test 的回复:]
该回复于2008-08-01 05:05:29被版主删除
[/Quote]
南南北北 2008-08-01
  • 打赏
  • 举报
回复
郁闷,代码里不让加颜色。。。

<sqlMap namespace="catelog">
<resultMap id="catelogResult" class="Catelog">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="catelogAttributeList" column="id"
select="catelogAttribute.findCatelogAttributeByCatelogId" />
</resultMap>

<select id="findCatelogById" parameterClass="int"
resultMap="catelogResult">
select id as id, name as name from CATELOG where id=#id#
</select>

</sqlMap>

----------------------------------------------------------------------

<sqlMap namespace="catelogAttribute">

<resultMap id="catelogAttributeResult" class="CatelogAttribute">
<result property="id" column="id" />
<result property="catId" column="catId" />
<result property="attributeId" column="attributeId" />
</resultMap>

<select id="findCatelogAttributeByCatelogId"
parameterClass="int" resultMap="catelogAttributeResult">
select id as id, catId as catId, attributeId as attributeId from
CATELOGATTRIBUTE where catId = #catId#
</select>
</sqlMap>
南南北北 2008-08-01
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 siyue 的回复:]
引用 7 楼 norwolfli 的回复:
你为什么要使用left join呢?
<select id=”getCategory” parameterClass=”int” resultMap=”categoryResult”>
select C.CAT_ID, C.CAT_DESCRIPTION
from CATEGORY where CAT_ID = #value#
</select>

这样就可以了,因为有 <result property=”productList” resultMap=”ProductCategory.productResult“/>
这句话,所以你得到的Category对象中的productList属性会自动添充。




[/Quote]

给你个例子。。。

<sqlMap namespace="catelog">
<resultMap id="catelogResult" class="Catelog">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="catelogAttributeList" column="id"
select="catelogAttribute.findCatelogAttributeByCatelogId" />
</resultMap>

<select id="findCatelogById" parameterClass="int"
resultMap="catelogResult">
select id as id, name as name from CATELOG where id=#id#
</select>

</sqlMap>

----------------------------------------------------------------------

<sqlMap namespace="catelogAttribute">

<resultMap id="catelogAttributeResult" class="CatelogAttribute">
<result property="id" column="id" />
<result property="catId" column="catId" />
<result property="attributeId" column="attributeId" />
</resultMap>

<select id="findCatelogAttributeByCatelogId"
parameterClass="int" resultMap="catelogAttributeResult">
select id as id, catId as catId, attributeId as attributeId from
CATELOGATTRIBUTE where catId = #catId#
</select>
</sqlMap>

zhj92lxs 2008-07-31
  • 打赏
  • 举报
回复
ibatis没用过,up

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧