【问题标题】:How do I do a JPA findAllBy native query for an object's property value when that object is within a List object, within an outer object?当该对象位于 List 对象内、外部对象内时,如何对对象的属性值执行 JPA findAllBy 本机查询?
【发布时间】:2022-01-20 17:37:33
【问题描述】:

我正在尝试编写我的游戏网络应用程序的匹配功能,User 实体包含一个属性,UserStats 具有 OneToMany 关系,其中存储 2 个 UserStat JPA 实体的列表,这些 userStat 实体有 2 组不同的统计数据,我需要的其中一项统计数据称为victoryScore。

如何搜索 UserStats.get(0).victoryScore 是特定值/值范围的用户?

我想我可能需要使用 JOIN,这是我的尝试:

 @Query(
            value = "SELECT * FROM user u JOIN u.userStats us WHERE u.location = :location AND u.rating BETWEEN :lowerRatingBound AND :upperRatingBound AND us.victoryScore BETWEEN :lowerVictoryScoreBound AND :upperVictoryScoreBound",
            nativeQuery = true)
    List<User> findChallengingUsers(@Param("lowerRatingBound") Integer lowerRatingBound, @Param("upperRatingBound") Integer upperRatingBound, @Param("lowerVictoryScoreBound") Double lowerVictoryScoreBound, @Param("upperVictoryScoreBound") Double upperVictoryScoreBound, @Param("location") String location);

还有错误:

No property victoryScore found for type User!

用户:

@Entity(name = "User")
@Table(name = "user")

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(name = "username", unique = true)
private String username;

@Column(name = "password")
private String password;

private String name;
private String email;
private String location;
private String bio;
private Integer rating;


@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = CascadeType.PERSIST)
private List<UserStats> userStats;
}

用户统计:

    @Entity()
@Table(name = "userStats")


  @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
public class UserStats {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userStatsId;

    private Integer victories;
    private Integer draws;
    private Integer defeats;

    private Double victoryScore;

private boolean isLeagueUserStats;

@JsonIgnore
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "user_id")
private User user;
}

这可能吗?

作为参考,我访问了我希望它如何搜索的胜利分数值:

user.getUserStats(0).getVictoryScore;

用户统计类也是一个域实体,因此也有自己的存储库接口。

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 尝试使用数据库控制台对数据库运行查询,您会发现它不是有效的查询。
  • @IgorFlakiewicz 我知道这不是一个有效的查询,这只是我从网上找到的类似情况的尝试,我只是不知道如何实际做到这一点。
  • 了解联接,通过反复试验编写有效查询,将查询复制粘贴到您的 @Query 注释中。 JPA 将按照您的代码进行映射,只需要您的 SQL 风格的有效查询。
  • 为什么设置native query=true?您似乎将 JPQL 与 SQL 混合和匹配:使用 JPQL 和您的实体,让 JPA 根据您的映射为您处理连接。类似于“select u from User u JOIN u.userStats us where ..”。区别只是选择 - 指定用户实例并使用字符串中的实体名称。至于映射, User.userStats 看起来不正确,因为您发布的 java 代码中没有 UserStats.user (您指定 mappedby="user" 这意味着必须定义它)。
  • 虽然使用 get(0) 不起作用,因为 User.userStats 列表本身是不确定的,并且没有排序或其他字段,您可以使用它来确定索引为 0 的内容。如果您想将一个指定为列表中的“第一个”,您必须向关系和实体添加更多以标记它 - 然后您可以在查询中使用它们。

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


【解决方案1】:

试试这个查询,

Query(value ="SELECT * FROM user u INNER JOIN userStats us ON u.id = us.user_id where (u.location = :location AND u.rating BETWEEN :lowerRatingBound AND :upperRatingBound) AND (us.victoryScore BETWEEN :lowerVictoryScoreBound AND :upperVictoryScoreBound)",nativeQuery = true)

【讨论】:

  • 这会导致错误,需要标识符,谢谢。
猜你喜欢
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多