【问题标题】:Hibernate Joins using CriteriaHibernate 使用条件连接
【发布时间】:2012-08-28 09:11:19
【问题描述】:

我正在尝试使用 Hibernate 访问持久数据以进行权限管理,但我对它非常陌生,并且难以获取我需要的数据。

我有一个带有 ID 和名称的 Users 表,一个带有 ID 和名称的 Groups 表,以及一个仅由链接的组 ID 和用户 ID 组成的用户/组映射。

我要做的是获取给定组的所有成员的名称,所以我要执行的标准 SQL 查询是这样的:

SELECT 
    u.NAME
FROM 
    USERS u
JOIN
    GROUP_USERS gu
ON
    u.ID = gu.USER_ID
JOIN
    GROUPS g
ON
    gu.GROUP_ID = g.ID
WHERE
     g.NAME = 'test'

但是,尽管看了好几个小时,我似乎还是什么都没有。

我想使用 Criteria,因为它们看起来更清晰,所以我的代码如下:

@Override
public final List<String> getGroupMembers(final String groupName) {
    @SuppressWarnings("unchecked")
    List<User> groupUsers = getHibernateTemplate().execute(new HibernateCallback<List<User>>() {

                @Override
                public List<User> doInHibernate(Session session) throws HibernateException, SQLException {
                    Criteria criteria = session.createCriteria(User.class)
                        .setFetchMode("GroupUsers", FetchMode.JOIN)
                        .setFetchMode("Group", FetchMode.JOIN)
                        .add(Restrictions.eq("name", groupName));
                    return criteria.list();
                }
            });

    List<String> groupUsernames = new ArrayList<String>();
    for (User groupUser : groupUsers) {
        groupUsernames.add(groupUser.getName());
    }
    return groupUsernames;
}

但是当我测试它时结果集是空的,根据日志执行的查询是这样的:

select this_.ID as M1_4_0_, this_.NAME as M2_4_0_ from USERS this_ where this_.NAME=?

我让 Hibernate 使用 hibernate.hbm2ddl.auto 创建表,但随后将其删除,这样表就完全符合 hibernate 的预期,但没有清理数据。

我们将不胜感激任何有关标准的帮助,因此提前致谢!

编辑:我正在使用 xml 映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.company">
    <class name="com.company.Group" table="GROUPS">
        <id name="id" column="ID" type="int">
            <generator class="identity"/>
        </id>
        <property name="name" column="NAME" type="java.lang.String" unique="true" not-null="true"/>
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.company">
    <class name="com.company.GroupUsers" table="GROUP_USERS">
        <composite-id>
            <key-many-to-one name="groupId" class = "Group" column="GROUP_ID" />
            <key-many-to-one name="userId" class = "User" column="USER_ID" />
        </composite-id>
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.company">
    <class name="com.company.User" table="USERS">
        <id name="id" column="ID" type="int">
            <generator class="identity"/>
        </id>
        <property name="name" column="NAME" type="java.lang.String" unique="true" not-null="true"/>
    </class>
</hibernate-mapping>

【问题讨论】:

  • 您正在对用户实体应用过滤器“名称”。您能否发布您的映射,看看您是如何描述您与 Hibernate 注释的关系的?
  • 感谢您的回复 - 我已添加映射文件。我将如何着手检索用户名但过滤组名?

标签: java sql hibernate join


【解决方案1】:

将对象映射到表的方式不会从使用 Hibernate 作为 ORM 中受益。考虑一个更面向对象的模型,例如:

class Group {
  private Set<User> users;
  // ...
}

class User {
  private Set<Group> groups;
  //..
}

所以,你有一个经典的多对多关联。 Here 你可以找到这样的 Hibernate 映射示例。

【讨论】:

    【解决方案2】:

    您不需要映射用户组表,只需将您的用户和组之间的关系定义为多对多关系,看看thisthis关于如何映射多-对多关系。

    在你的情况下,它看起来像:

    <hibernate-mapping package="com.company">
      <class name="com.company.User" table="USERS">
    
        <id name="id" column="ID" type="int">
            <generator class="identity"/>
        </id>
        <property name="name" column="NAME" type="java.lang.String" unique="true" not-null="true"/>
    
    <many-to-many name="userGroups"
        target-entity="com.company.Group">
       <join-table name="YOUR_USER_GROUP_TABLE">
        <join-column name="USER_ID" />
        <inverse-join-column name="GROUP_ID" />
       </join-table>
    </many-to-many>
    
    </class>
    

    并使用组实体中的名称字段过滤您的用户,例如:

    Criteria criteria = session.createCriteria(User.class);  
    criteria.createAlias("userGroups", "usrGrp",CriteriaSpecification.LEFT_JOIN); 
    criteria.add( Restrictions.eqProperty("usrGrp.name", "test") )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 2011-06-14
      • 2013-12-30
      • 2017-11-14
      相关资源
      最近更新 更多