Hibernate4多对多查询出重复的记录

sunxing007 2013-12-13 01:26:05
很简单很常见的关联关系, 我却遇到问题,有工会会员Member和工会俱乐部Club,是多对多关系,如下代码:

@Entity
@Table(name = "tu_member")
public class Member extends BaseEntity<Member>{
private static final long serialVersionUID = 5939777389315777218L;
private String name;
private String gender;
private Date birthday;
private String company;
private String department;

@ManyToMany(targetEntity = Club.class, cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@JoinTable(name = "tu_club_member", joinColumns = { @JoinColumn(name = "member_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "club_id", nullable = false) })
@ForeignKey(name = "none", inverseName = "none")
private List<Club> clubs;

public List<Club> getClubs() {
return clubs;
}
public void setClubs(List<Club> clubs) {
this.clubs = clubs;
}
public String getName() {
return name;
}
。。。。。。


@Entity
@Table(name = "tu_club")
public class Club extends BaseEntity<Club>{

private static final long serialVersionUID = 1058338119416690351L;
private String name;
private String company;
private String description;
private String coordinator;

@ManyToMany(targetEntity = Member.class)
@JoinTable(name = "tu_club_member", joinColumns = { @JoinColumn(name = "club_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "member_id", nullable = false) })
@ForeignKey(name = "none", inverseName = "none")
private List<Member> members;

public List<Member> getMembers() {
return members;
}
public void setMembers(List<Member> members) {
this.members = members;
}
public String getName() {
return name;
}
。。。。。。

Dao和service都是非常普通的写法。
然后我就写了个简单的测试程序。

Member member = new Member();
member.setName("Member1");
member.setBirthday(new Date());
member.setGender("Male");
member.setCompany("CSTS");
member.setDepartment("ICG V");

Club club = new Club();
club.setCompany("CSTS");
club.setName("Swimming");

Club club1 = new Club();
club1.setCompany("CSTS");
club1.setName("Table Tennies");

List<Club> list = new ArrayList<Club>();
list.add(club);
list.add(club1);
member.setClubs(list);
memberService.save(member);

Club club2 = new Club();
club2.setName("Drink");
club2.setCompany("CSTS");
member.getClubs().add(club2);
memberService.save(member);
List<Member> members = memberService.findAll();

这个程序应该出现的结果是 一个Member,它关联了3个Club;但是出来的结果吓了我一跳,居然在页面上显示了3条一样的Member。但是数据库只有一条。
我知道出3条的原因是采用左连接造成的:

select
this_.id as id11_1_,
this_.birthday as birthday11_1_,
this_.company as company11_1_,
this_.department as department11_1_,
this_.gender as gender11_1_,
this_.name as name11_1_,
clubs2_.member_id as member1_11_3_,
club3_.id as club2_13_3_,
club3_.id as id10_0_,
club3_.company as company10_0_,
club3_.coordinator as coordina3_10_0_,
club3_.description as descript4_10_0_,
club3_.name as name10_0_
from
tu_member this_
left outer join
tu_club_member clubs2_
on this_.id=clubs2_.member_id
left outer join
tu_club club3_
on clubs2_.club_id=club3_.id


请问我错在哪里? 该怎么配置才能只出现一条?
...全文
449 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
return this.getSession().createCriteria(Member.class).returnMaps().list(); 改为这样应该也可以。
sunxing007 2013-12-13
  • 打赏
  • 举报
回复
然后我看到别人给的解决方法是: return this.getSession().createCriteria(Member.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).setFetchMode("clubs", FetchMode.JOIN).list();
sunxing007 2013-12-13
  • 打赏
  • 举报
回复
引用 6 楼 hjw506848887 的回复:
把club类上的@JoinTable配置去掉试试。。。。
谢谢关注. 我早上又试验了3个小时, 我发现是由于查询的方式引起的. return this.getSession().createQuery("from Member").list();//这样就不会重复. return this.getSession().createCriteria(Member.class).list();//这样就会重复. 不知道有什么解释.
  • 打赏
  • 举报
回复
把club类上的@JoinTable配置去掉试试。。。。
  • 打赏
  • 举报
回复
引用 4 楼 sunxing007 的回复:
[quote=引用 1 楼 hjw506848887 的回复:] 应该是因为你的club查询时自动加载了member,一共三条club,所以也会查询出三条member。不知道你页面上和后台部分内容是怎么样写的啊。。。
是一个Member加入了3个俱乐部Club, 现在我查Member列表, 并顺带把他们所属的Club查出来. 后台代码都是非常通用的Query.list(), Criteria.list()之类的. 页面代码和本文描述的问题没有关系.[/quote]如果后台没写错,看打印的sql语言,我觉得还是你配置出问题了。。。
sunxing007 2013-12-13
  • 打赏
  • 举报
回复
引用 1 楼 hjw506848887 的回复:
应该是因为你的club查询时自动加载了member,一共三条club,所以也会查询出三条member。不知道你页面上和后台部分内容是怎么样写的啊。。。
是一个Member加入了3个俱乐部Club, 现在我查Member列表, 并顺带把他们所属的Club查出来. 后台代码都是非常通用的Query.list(), Criteria.list()之类的. 页面代码和本文描述的问题没有关系.
sunxing007 2013-12-13
  • 打赏
  • 举报
回复
引用 2 楼 fangmingshijie 的回复:
用HashSet把members包装一下。
你觉得我的配置有没有问题? 我以前没有深入使用过Hibernate, 如果我所描述的是正常的话, 那hibernate也太不好用了, 因为这种case太正常不过了.
  • 打赏
  • 举报
回复
用HashSet把members包装一下。
  • 打赏
  • 举报
回复
应该是因为你的club查询时自动加载了member,一共三条club,所以也会查询出三条member。不知道你页面上和后台部分内容是怎么样写的啊。。。
sunxing007 2013-12-13
  • 打赏
  • 举报
回复
引用 11 楼 baohuan_love 的回复:
Hibernate中,left join、inner join以及left join fetch区别http://www.iteye.com/problems/6491
谢谢
  • 打赏
  • 举报
回复
Hibernate中,left join、inner join以及left join fetch区别http://www.iteye.com/problems/6491
  • 打赏
  • 举报
回复
hibernate left join fetch 使用方法解决重复数据:http://blog.csdn.net/xiaomaha/article/details/6623557

67,512

社区成员

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

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