Hibernate(使用Spring)查询具有多对多

时间:2011-07-08 10:16:09

标签: java hibernate spring

我有user和userRole表,它具有多对多关系。我有以下Hibernate映射:

<hibernate-mapping>
<class name="domain.User" schema="dbo" table="Users">
<id name="userId" type="int">
  <column name="UserId"/>
  <generator class="native"/>
</id>
<property name="username" type="string">
  <column name="Username" not-null="true"/>
</property>
<property name="password" type="string">
  <column name="Password" not-null="true"/>
</property>
<set cascade="all" inverse="true" name="userRole" table="UserRoleRelationships">
  <key>
    <column name="UserId"/>
  </key>
  <many-to-many class="domain.UserRole" column="RoleId" />
</set>
</class>
</hibernate-mapping>

<hibernate-mapping>
<class name="domain.UserRole" schema="dbo" table="UserRoles">
<id name="roleId" type="int">
  <column name="RoleId"/>
  <generator class="native"/>
</id>
<property name="role" type="string">
  <column name="Role" not-null="true"/>
</property>
</class>
</hibernate-mapping>

我的豆子看起来像:

public class User {

private Integer userId;
private String username;
private String password;
private Set<UserRole> userRole;

// getters and setters
}

public class UserRole {

private Integer roleId;
private String role;
private User user;

// getters and setters
}

按用户名选择用户的查询如下:

public List<User> getWithUsername(String username){
    return getHibernateTemplate().find("from User as u "
            + "inner join fetch u.userRole "
            + "where u.username = '" + username + "'" );
}

问题在于,当我尝试使用以下循环打印出来时:

for (User u : list){
            System.out.println(u.getUsername());

            for (UserRole ur : u.getUserRole()){
                System.out.println(ur.getRole());
            }  
        }

将它打印出来加倍:

Username: jorgen
User role: User
User role: Admin
Username: jorgen
User role: User
User role: Admin

我做错了什么?请帮助:)

2 个答案:

答案 0 :(得分:0)

你没有做错任何事。 Hibernate就是这样做的,它与构建查询的方式有关。如果你在SQL中做同样的事情,你也会有两行。

解决这个问题的方法有两种:

  • 您可以使用DistinctRootEntityProjection但据我所知,这只适用于条件
  • 您可以自己过滤掉重复项(我建议您在调用hibernate的类中封装该逻辑)。最简单的方法就是将物品扔进一套,然后再将它们拿出来。

答案 1 :(得分:0)

我找到了一个符合标准的解决方案:

public List<User> getWithUsername(String username){

    Criteria criteria = getSession().createCriteria(IWUser.class)
    .add(Restrictions.like("username", username))
    .setFetchMode("userRole", FetchMode.EAGER)
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

    return criteria.list();

}