Hibernate的多对多如何只插入关联?

masse 2007-12-28 11:50:30
用户和团队,之间是多对多关系。
如果用户A团队A现在在数据库里面都有了,
现在需要在之间建立一个关联


teama = dao.getTeam(1); // 拿到teama
persona = dao.getPerson(1); // 拿到teamb
teama.addPerson(persona); // 建立关联
dao.saveTeam(teama); // 保存结果
hibernate执行的顺序是
(1)更新Team的信息:update Team set name=?.....
(2)删除teama相关的关联 : delete from Team_Person where teamId=?
(3)建立新的关联:insert into Team_Person values(?,?)

其实对我的应用场景来说,只需要执行一句sql就够了,但是Hibernate却给我执行了至少3句。
当我之前Team下的用户较多时,
甚至执行非常多的语句。

请问这个如何改进?如何让它只执行我想要的那句?


Team(id INT)

-- 人员
Person( id INT )

-- 小组和人员的多对多关系
Team_Person(
teamId INT,
personId INT,
FOREIGN KEY(teamId) REFERENCES Team(id),
FOREIGN KEY(personId) REFERENCES Person(id)
)



@Entity
public class Team{
private int id;
@Id
public int getId(){return id;}

@ManyToMany
public Collection<Person> persons;
}

@Entity
public class Person{
private int id;
@Id
public int getId(){return id;}

@ManyToMany
public Collection<Team> teams;
}

...全文
469 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
睿音 2007-12-29
  • 打赏
  • 举报
回复
终于找到这个帖子了,CSDN的IM实在是不会用啊。
我的理解是这个样子的,在我们现在的大部分领域模型中,往往是可以抽象成个体实体和关系实体(瞎说的没什么根据,只是经验的一个感觉),而在现实业务中经常发生变动的往往是关系实体。举个例子:比如说在银行交互体系下,往往帐户实体变动相对是少的,相比变动大的是在这些用来记录在这些帐户实体之间发生的变动的关系实体。所以我现在的常用做法就是像上次在你的那个帖子里写的那样,将关系放在了业务层,将关系实体抽象出来。上次并没有详细的说明这种方法的优点,这次简单说说吧。
我觉得第一个优点--解耦:如果将关系做成个体实体之间的关系,那么个体实体和关系是强耦。那么若后期个体实体需要扩展,比如说我曾经有过这样的经历,在实现一套依托协议的系统中,起初的协议和后期要求的协议实体抽象是一样的,但是他们的关系不一样。比如下图:

在协议1的业务关系中,主动关系与被动关系是直接的关系。而在协议2的业务关系中,主动关系与被动关系由一个关联的实体关联起来。(关联实体不是我说的关系实体)。这样我在协议1的实现基础上再实现协议2的业务关系是非常困难的,如果我将关系抽出来进行抽象,这样就变成了各自独立的实体。我可以在向上次在你的帖子里那样。我可以在Service里面实现任何的关系,通过DAO层去实现。
我觉得第二个优点--性能:这个在masse你的这个帖子就能体现。就像你的现在的这个关系体系。若我抽像出来关系实体。我在维护常用的业务逻辑时仅仅使用一条sql。像楼主这种方式,我在增加用户A和团队A的关系时,只需要在用户A和团队A的关系实体中增加一条记录。
缺点:开发时会过于麻烦。因为关系完全需要你去控制,如果没有一个好的实体层的体系模板是挺麻烦的。我现在用的模板是参考了SpringSide的后来又增加了一些自己的一些东西做的。
qingyuan18 2007-12-29
  • 打赏
  • 举报
回复
你的hibernate的OR配置是否有误,我记得Many-to-Many这种情况是可以指定关联表的
把你的Hibernate配置文件贴出来看看吧
karlpan01 2007-12-29
  • 打赏
  • 举报
回复
不太清楚这个问题!抱歉!
masse 2007-12-29
  • 打赏
  • 举报
回复
另外,我的环境是spring2+hibernate3
谢谢
masse 2007-12-29
  • 打赏
  • 举报
回复
谢谢,我就是这么写的。
只是在上面的代码里面省略了。

我的数据比较多,可能有几十万上百万,
所以没有在ManyToMany的关系上设置fetch = FetchType.EAGER

请问这种大数据量的情况下,如何单纯的设置关联呢?
睿音 2007-12-29
  • 打赏
  • 举报
回复
若并发量级大,就别使用springside的封装了,自己做系统架构的设计。不过我欣赏的是springside中很精妙的设计。可能是我以前没有见识过,但是我对他们中使用泛型做基础DAO这个方法是很赞叹的。所以我取用了这个部分,在次基础上做了我现在的DAO这部分的架构设计。不过,这种设计我并没有在并发量很大的系统架构上试过,风险较大。回头有机会再试试吧。而且springside本身也不是为大级量并发项目设计的。这点从使用的JMS可以看出来。我没有做过测试,但是activemq应该是适应不了masse你说的这种架构。
我现在使用的这种将个体实体与关系实体解耦的设计其实就是在一个并发量比较大的项目上改进的。开始也是做的关系,可以性能上总是达不到要求,延迟加载也满足不了。后来就只能从抽象出来的模型上进行分析。于是上面写的那个部分就算是当时的一个理解吧。
其实架构并不一定需要使用spring+hibernate.我是比较热衷于spring的,虽然看到不少说其容器效率怎么怎么样的文章。但是我的胆子还是比较小,google-guice这种东西我不敢用。hibernate若使用oracol.openJPA应该更加好一些。毕竟hibernate虽然支持JPA但是有些个,例如在uuid这里。至今我还是很头疼的,只能转赴openJPA来解决。
性能问题可以通过架构来解决,不一定非要压在业务层和领域模型这里。OK,要开会。
masse 2007-12-29
  • 打赏
  • 举报
回复
我现在就是想用springside的封装。
主要基于效率的考虑。

如果完全使用这个封装,小数据还行,
我的数据接近千万,
很够呛啊
睿音 2007-12-29
  • 打赏
  • 举报
回复
Ps.在使用JPA标记时,最好将主键定义成long型。允空时定义成Long型。JPA推荐这样使用。
另。TO:qingyuan18 masse用的是JPA标记,是没有.hbm.xml 在JPA下可以使用
@JoinTable(name="xxx-xxx",....

来指定关联表。
但是我的感觉若不级联就不能更改关联表,若级联,只有在改变关系持有实体时级联才发生改变。
jyh149129 2007-12-29
  • 打赏
  • 举报
回复
试试如下修改是否可行
@ManyToMany(mappedBy="teams")
public Collection<Person> persons

67,518

社区成员

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

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