职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 1048|回复: 10

这样的情况,Hibernate应该怎么设计映射

[复制链接]
愚人 发表于 2011-8-30 10:10 | 显示全部楼层 |阅读模式
假设有这样的需求:

1、系统中有一个实体叫商品
2、用户可以跟踪商品

所以就有了这样的2个类
  
class Product { id, name }   
class Track { id, product, user, time }  

class Product { id, name }
class Track { id, product, user, time }


现在又有这样的一个功能,要在首页显示商品的列表,但是如果这个商品用户有跟踪,则显示出用户跟踪的相关信息,最后的效果可能是这样的

-商品1 - 2011-01-01开始跟踪
-商品2 - 无跟踪
-商品3 - 2011-12-11开始跟踪

如果我们有2张表的话,肯定会写这样的语句:
  
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user = {currentUser.id}  

select * from Product p
right outer join Track t
  on t.product = p.id
where t.user = {currentUser.id}


这里就有一个问题:根据原始的设计,Product和Track肯定是1:N的关系,但是一但加入了currentUser.id这个条件之后,Product和Track就是1:1的关系

那么,合理地说,我现在需要前面所述的一个列表,从对象的设计上,我会有这样一个类

  
class ProductWithTrack extends Product { track }  

class ProductWithTrack extends Product { track }


这个类就在Product的基础上,增加了与之关联的Track对象,关系是1:1的,非常合理的设计

但是如果撞上Hibernate,这个映射就变得十分困难了:

1、假设使用one-to-one,则要求Product和Track共享主键,显然不会
2、假设使用one-to-many,则要求ProductWithTrack中的track属性是一个集合,显然不是
3、假设使用many-to-one,则要求“外键字段”在Product类里,显然不可能

所以现在这就成了一个看似无解的问题了,即便使用Projection似乎也没办法完成这句outer join的查询

可能你会说,数据库上这是1:N的,那么对象明显应该用1:N的模型啊。但是ORM的目的是什么呢?难道不是为了让我基于对象来建模,随后可以映射到关系型数据库吗?不然为啥不叫ROM呢?

总之,先在这里求个助,不知道这样的情况,有没有办法解决,当然要满足一个要求,我的类里面必须是1:1的关系。

gz-vps 发表于 2011-8-30 10:10 | 显示全部楼层
首先你的:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user = {currentUser.id}  

应该改成:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user.id = {currentUser.id}  

其次不明白你为什么还要引入一个类。。怎么就变成了1对1的关系了。。。
你的意思是每个用户只能对一个产品有一条追踪记录吗

无处不在 发表于 2011-8-30 10:11 | 显示全部楼层
如果是的话,在你的user表作到product表的双向多对多关联就好了

feiguo 发表于 2011-8-30 10:11 | 显示全部楼层
不知道我的理解对不对。
用户-------跟踪-------商品
首先有一个 用户 对象和一个 商品 对象,
一个用户可以跟踪多个商品,同样一件商品可以有很多个跟踪用户,
那么用户与商品就是多对多的关系,
继而生成第三张表,也就是 跟踪(表)


走就走吧 发表于 2011-8-30 10:11 | 显示全部楼层

首先你的:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user = {currentUser.id}  

应该改成:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user.id = {currentUser.id}  

其次不明白你为什么还要引入一个类。。怎么就变成了1对1的关系了。。。
你的意思是每个用户只能对一个产品有一条追踪记录吗

是的,一个用户对一个商品只能有一个追踪记录,即什么时候开始追踪以及追踪的状态,从对象的角度来看,很明显对于一个用户,Product和Track是1:1的关系

hxy 发表于 2011-8-30 10:11 | 显示全部楼层

不知道我的理解对不对。
用户-------跟踪-------商品
首先有一个 用户 对象和一个 商品 对象,
一个用户可以跟踪多个商品,同样一件商品可以有很多个跟踪用户,
那么用户与商品就是多对多的关系,
继而生成第三张表,也就是 跟踪(表)


如果套用关系型的数据结构是这样的没有错,如果是多对多,其实就是
Product { List<Track> }
Track { Product, User }
User { List<Track> }
但问题就在于,如果当前的用户已经给定了,那么一个Product对这个用户来说只可能有一条Track,因此希望Product里的Track是一个对象,而不是一个List,不然这个List永远只会有1项(因为加了CurrentUser的条件限制),List就失去意义了

走就走吧 发表于 2011-8-30 10:11 | 显示全部楼层

如果是的话,在你的user表作到product表的双向多对多关联就好了

双向多对多在对象定义上无疑是一个List,但既然一个User对一个Product只会有一个Track,那我从对象的角度来考虑,Product里肯定只会有一个Track,且我上面写的SQL条件也确实只会对每个Product连接出一个Track,所以我实在无法接受在Product里有一个List这样的做法……或许对于想把关系型数通过通用的ORM转成如此自定义的对象关系,不太现实吧……

fossil 发表于 2011-8-30 10:11 | 显示全部楼层

首先你的:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user = {currentUser.id}  

应该改成:
select * from Product p   
right outer join Track t   
  on t.product = p.id   
where t.user.id = {currentUser.id}  

其次不明白你为什么还要引入一个类。。怎么就变成了1对1的关系了。。。
你的意思是每个用户只能对一个产品有一条追踪记录吗

是的,一个用户对一个商品只能有一个追踪记录,即什么时候开始追踪以及追踪的状态,从对象的角度来看,很明显对于一个用户,Product和Track是1:1的关系


我觉得你理解本末倒置了。首先对象关系并不是一对一的情况,而是你查询语句限定了查出一条记录而已。也就是说,
你是从List里面再通过限定查询从List里面过滤出唯一的一条记录。这同样是一对多,而不是一对一。

所以我觉得你去再设计一个1对1的类出来时完全没有必要的




钰云 发表于 2011-8-30 10:12 | 显示全部楼层
无论你从什么角度来思考,都不是1对1,是你理解偏差了

Jethro 发表于 2011-8-30 10:12 | 显示全部楼层
如果你非要弄一对一也不是不可以,hql动态组装对象是可以做到的
pdbgtvtd 发表于 2012-5-21 16:06 | 显示全部楼层

成双结对 10新6

母亲河黄河早已变为我们的干娘了。
长江也快变成干爹了。
这下好了,他们终于成双结对了。


红酒木瓜靓汤丰胸
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-2 23:01 , Processed in 0.155443 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表