【问题标题】:Hibernate Named Query - join 3 tablesHibernate 命名查询 - 连接 3 个表
【发布时间】:2012-01-14 00:34:01
【问题描述】:

我有 3 个 bean:组织、角色、用户

角色 - 组织关系 - @ManyToOne

角色 - 用户关系 - @ManyToMany

组织:

    @Entity
    @Table(name = "entity_organization")
    public class Organization implements Serializable {

        private static final long serialVersionUID = -646783073824774092L;

        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        Long id;

        String name;

        @OneToMany(targetEntity = Role.class, mappedBy = "organization")
        List<Role> roleList;

...

角色:

    @Entity
    @Table(name = "entity_role")
    public class Role implements Serializable {

        private static final long serialVersionUID = -8468851370626652688L;

        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        Long id;

        String name;

        String description;

        @ManyToOne
        Organization organization;

...

用户:

    @Entity
    @Table(name = "entity_user")
    public class User implements Serializable {

        private static final long serialVersionUID = -4353850485035153638L;

        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        Long id;
        @ManyToMany
        @JoinTable(name = "entity_user_role",
                joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName =                     "id"))
        List<Role> roleList;

...

所以我需要获取指定用户的所有组织(首先我需要选择所有用户角色,然后选择所有具有此角色的组织)

我有一个实现此逻辑的 sql 语句(例如,我选择 id = 1 的用户):

SELECT * FROM entity_organization AS o 
INNER JOIN entity_role r ON r.organization_id = o.id 
INNER JOIN entity_user_role ur ON ur.role_id=r.id 
WHERE ur.user_id = 1

如何使用休眠命名查询机制来实现这一点? 谢谢!

【问题讨论】:

    标签: mysql sql hibernate join named-query


    【解决方案1】:

    @NamedQuery

    ​​>

    我在Organization 实体类上创建了以下@NamedQuery。

    @NamedQuery(name = "query", query = "SELECT DISTINCT o " +
        "FROM Organization o, User u " +
        "JOIN o.roles oRole " +
        "JOIN u.roles uRole " +
        "WHERE oRole.id = uRole.id AND u.id = :uId")
    public class Organization { ...
    

    (我使用标准的 JPA 注释,但我的提供者是 Hibernate。)

    测试

    这是我运行的测试。

    EntityManager em = ...
    TypedQuery<Organization> q = em.createNamedQuery("query", Organization.class);
    q.setParameter("uId", 1); // try it with 1L if Hibernate barks about it
    for (Organization o : q.getResultList())
      System.out.println(o.name);
    

    使用下面的表格和示例数据,输出

    A
    B
    

    请看看它是否适合你。

    表格

    CREATE TABLE `organization` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
    
    CREATE TABLE `role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      `description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      `organization_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
    
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`id`)
    );
    
    CREATE TABLE `user_has_role` (
      `user_id` int(11) NOT NULL DEFAULT '0',
      `role_id` int(11) NOT NULL DEFAULT '0',
      PRIMARY KEY (`user_id`,`role_id`)
    );
    
    ALTER TABLE `role` ADD CONSTRAINT `cst_organization_id` 
      FOREIGN KEY `fk_organiztaion_id` (`organization_id`)
        REFERENCES `organization` (`id`);
    

    (我用的和你的有点不同,但应该没太大关系。)

    样本数据

    `organization`
    +----+------+
    | id | name |
    +----+------+
    |  1 | A    |
    |  2 | B    |
    +----+------+
    
    `role`
    +----+------+-------------+-----------------+
    | id | name | description | organization_id |
    +----+------+-------------+-----------------+
    |  1 | A    | a           |               1 |
    |  2 | B    | b           |               1 |
    |  3 | C    | c           |               2 |
    +----+------+-------------+-----------------+
    
    `user`
    +----+
    | id |
    +----+
    |  1 |
    |  2 |
    |  3 |
    +----+
    
    `user_has_role`
    +---------+---------+
    | user_id | role_id |
    +---------+---------+
    |       1 |       1 |
    |       1 |       2 |
    |       1 |       3 |
    |       2 |       1 |
    |       3 |       1 |
    |       3 |       3 |
    +---------+---------+
    

    【讨论】:

    • 它不起作用。 id = 2 的用户具有 id=1 的角色,因此他必须仅在组织 id = 1 中,但查询返回 2 行
    • @BraginiNI 我很草率,只检查了uId = 1 的查询结果。对于那个很抱歉。我已经更新了我的答案。对于 ID:1、2 和 3,它返回:A 和 B、B i> 和 A 和 B。如果没有 DISTINCT 关键字,则会返回重复的结果。
    • 谁能澄清一下我们是如何从组织类中知道 o.roles 值的,因为它的属性仅为 roleList。
    【解决方案2】:

    尝试如下 HQL:

    select ur.roleList.organization from User ur where ur.id = 1 
    

    它会给你List&lt;Organization&gt;。

    【讨论】:

    • 这是“ur.roleList.organization”部分中命名查询语法的错误,因为我认为它不是可用的语法。 “ur.roleList 很好用”
    • 错误创建文件中定义的名称为“accountDaoImpl”的 bean 原因:org.hibernate.HibernateException:命名查询中的错误:Organization.findOrganizationsByUser
    猜你喜欢
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 2015-12-11
    • 1970-01-01
    • 2014-09-28
    相关资源
    最近更新 更多