【问题标题】:How to get a HashMap result from Spring Data Repository using JPQL?如何使用 JPQL 从 Spring Data Repository 获取 HashMap 结果?
【发布时间】:2020-11-17 23:54:18
【问题描述】:

我目前使用 UserShopRole 之间的 Map 实现了三元关系。 所以在我的用户实体中我有这个映射:

User.java

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

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private int id;

@Basic(fetch = FetchType.LAZY, optional = false)
private String uuid;

@NotBlank(message = "First name can not be empty")
@Column(name = "usFname")
private String usFname;

@NotBlank(message = "Username can not be left empty")
@Column(name = "us_lname")
private String usLname;

@NotBlank(message = "Email field can not be empty")
@ValidEmail
    @Column(name = "usEmail", unique = true)
    @Basic(fetch = FetchType.LAZY, optional = false)
    private String usEmail;
 //this is the actual mapping
//a user can have a list of shops, but one role assigned for each shop
@ManyToMany
    @MapKeyJoinColumn(name = "shop_fk")
    @JoinTable(name = "user_shop_role",
            joinColumns = @JoinColumn(name = "user_fk"), inverseJoinColumns = @JoinColumn(name = "role_fk"))
    private Map<Shop, Role> shopRoleMap = new HashMap<>();
//GETTERS AND SETTERS,
}

Role.java

@Entity
@Table(name = "ro_roles")
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private int id;

@Column(name = "rn_role_name")
private String roleName;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getRoleName() {
    return roleName;
}

public void setRoleName(String roleName) {
    this.roleName = roleName;
}

}

Shop.java

@Entity
@Table(name = "sh_shops")
public class Shop {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(nullable = false)
private int id;

@NotBlank(message = "Shop name can not be left blank")
private String sh_name;

@NotBlank(message = "please provide shop icon")
private String sh_icon;

@NotBlank(message = "please fill the shop description")
private String sh_description;

@NotBlank
private String sh_tag;
//setters, getters, equals, hashCode methods.
}

此映射为我提供了数据库中另一个具有 user_fkshop_fkrole_fk 的表 (user_shop_role)这很可爱。 困难的一点是使用 Spring Data JPA 进行查询并将结果作为给定用户的 HashMap 获取,如下所示: HashMap for the logged in user。

在 UserRepository 层我试过这个:

接口 UserRepository 扩展了 JpaRepository,我有这个查询...

@Query("SELECT u FROM User u join shopRoleMap m where key(m)= usEmail")
     public HashMap<Shop, Role> findByUser(String email);


}

如何获取使用地图集合映射的三元关系的结果,以获取商店列表和相应的角色值。更多的是一个键值结果?

【问题讨论】:

  • 尝试从 JPA 生成的映射表中获取 ShopRole 的 ID。然后,使用这些 id 获取它们的对象实体并将它们放入您的 HashMap 中。您不能直接查询并将结果添加到 HashMap 中。
  • 如果关系映射正确且有效。您是否尝试过“SELECT m FROM ...”而不是“SELECT u FROM”。所以你会以这种方式(m)返回关系,而不是用户对象(u)。
  • @User-Upvotedon'tsayThanks,你不知道什么是三元关系......你不知道用例。恕我直言,你只是在咆哮......
  • @User-Upvotedon'tsay谢谢,请在此处找到我的用例以获取推导映射:[stackoverflow.com/questions/62793067/…
  • @Brother 也不行

标签: java spring-boot jpa spring-data-jpa


【解决方案1】:
  • 存储库方法。
    @Repository
    public interface UserRepository
            extends JpaRepository<User, Integer> {
    
        @Query("SELECT key(m), value(m) FROM User u join u.shopRoleMap m" +
                " where u.usEmail = :email")
        List<Object[]> findByUserEmail(String email);
    
    }

  • 生成的查询。
    select
        shop3_.id as id1_1_0_,
        role2_.id as id1_0_1_,
        shop3_.sh_description as sh_descr2_1_0_,
        shop3_.sh_icon as sh_icon3_1_0_,
        shop3_.sh_name as sh_name4_1_0_,
        shop3_.sh_tag as sh_tag5_1_0_,
        role2_.rn_role_name as rn_role_2_0_1_ 
    from
        us_users user0_ 
    inner join
        user_shop_role shoprolema1_ 
            on user0_.id=shoprolema1_.user_fk 
    inner join
        ro_roles role2_ 
            on shoprolema1_.role_fk=role2_.id 
    inner join
        sh_shops shop3_ 
            on shoprolema1_.shop_fk=shop3_.id 
    where
        user0_.us_email=?

用上面的代码和另一种方式更新

Github 存储库 - https://github.com/kavi-kanap/stackoverflow-6313585

【讨论】:

  • @KavithanKaran 我必须说谢谢并接受答案,因为它部分工作。但是在此代码上:public Shop getMyShops(String email){ Map&lt;Shop, Role&gt; shopRole = userRepository.findbyUserEmail(email); Shop shop = new Shop(); for (Map.Entry&lt;Shop, Role&gt; entry : shopRole.entrySet()) { shop = entry.getKey(); System.out.println("Shop is: "+shop); Role role = entry.getValue(); System.out.println("The role value is: "+role.getRoleName()); } return shop; } 我可以获得角色但商店返回 null
  • 更新后的答案仍然给出 shop 和 null 并且 entryset().getvalue() 给出一个强制转换异常
  • 我插入了一些数据并使用了各种组合。不幸的是,如果我使用List&lt;Object[]&gt; 作为返回类型,那么只有spring-data-jpa 填充两者
  • 请问您是如何从返回的类型中填充两者的?
  • 当我在更新的答案中使用List&lt;Object[]&gt; 时,每个数组包含两个元素,一个商店和一个角色。
【解决方案2】:

Spring Data JPA 有一个名为 Property Expressions 的功能,您可以在其中访问子实体或相关实体

例如

List&lt;Shop&gt; findByUser_email(String email);

更多详情参考这里

Spring Data JPA doc

Sample example

【讨论】:

  • 如果我这样做,我将获得该特定用户的商店列表。但我需要的是获得该用户对每个商店的商店和特定角色。
  • 能否请您添加您的实体类 Shop、Role 和 User,因为它没有发布问题我给出了示例答案 findByUser_email(String email)
  • 我已经添加了请求的实体。
猜你喜欢
  • 1970-01-01
  • 2015-02-18
  • 2018-05-16
  • 2013-03-22
  • 2019-04-06
  • 2015-04-12
  • 2013-11-28
  • 2015-05-26
  • 2017-06-22
相关资源
最近更新 更多