Spring Data JPA:如何仅获取具有子实体 ID 的父实体而不是整个子实体

问题描述 投票:0回答:1

我有一个带有实体玩家和评级的 Spring Data JPA 设置。在我的用例中,我想通过 ID 检索特定用户的所有评级。但是,我不想获取每个评级的完整用户实体;相反,我只需要用户 ID,或者什么都不需要,类似于它在数据库中的存储方式。

有没有办法在 Spring Data JPA 中实现这一点,也许通过自定义查询或投影,通过避免为每个评级不必要地加载完整的用户实体来优化性能?

有优化的方法吗?目前它只是在调用后映射到 DTO,我认为它没有很好地优化。

实体

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Rating {

    @EmbeddedId
    private RatingId ratingId;

    @ManyToOne
    @MapsId("playerId")
    @NotNull
    private Player player;

    @ManyToOne
    @MapsId("gameId")
    @NotNull
    private Game game;

    private float points;

    @ManyToOne
    private Platform platform;

    private Long startDate;

    private Long endDate;

    private Status status;

    public Rating(Player player, Game game) {
        this.ratingId = new RatingId(player.getId(), game.getId());
        this.player = player;
        this.game = game;
    }
}

@Entity
@EqualsAndHashCode
@NoArgsConstructor
@Getter
@Setter
public class Player {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Setter(AccessLevel.NONE)
    @Column(updatable = false)
    private Long id;

    @NotBlank
    @Size(max = 20)
    @Column(unique = true)
    private String username;

    @NotBlank
    @Size(max = 50)
    @Email
    @Column(unique = true)
    private String email;

    @NotBlank
    @Size(max = 120)
    private String password;

    @EqualsAndHashCode.Exclude
    private Set<Role> roles = new HashSet<>();

    public Player(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
    }

}

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class RatingId implements Serializable {

    private Long playerId;
    private Long gameId;
}

存储库

@Repository
public interface RatingRepository extends JpaRepository<Rating, RatingId> {
    List<Rating> findAllByPlayerId(Long playerId);
}

当我直接在数据库中执行时:

database=# select * from rating where rating.player_id = 1;

 end_date | points | start_date | status | player_id | game_id | platform_id
----------+--------+------------+--------+-----------+---------+-------------
          |    1.5 |            |      0 |         1 |    9174 |           6
java spring-boot hibernate spring-data-jpa spring-data
1个回答
0
投票

您可以在 Spring Data JPA 中使用自定义查询或投影。实现此目的的一种方法是使用 DTO(数据传输对象)投影来仅检索必要的信息。

public class RatingDTO {
    private Long playerId;
    private float points;
    private Long startDate;
    private Long endDate;
    private Status status;

    // Constructor, getters, and setters
}
@Repository
public interface RatingRepository extends JpaRepository<Rating, RatingId> {

    @Query("SELECT new com.example.dto.RatingDTO(r.player.id, r.points, r.startDate, r.endDate, r.status) FROM Rating r WHERE r.player.id = :playerId")
    List<RatingDTO> findAllByPlayerId(Long playerId);
}

现在,当您调用

findAllByPlayerId
方法时,它将返回仅包含必要信息的
RatingDTO
对象列表,而不获取完整的
Player
实体。

记得根据你的项目结构调整包名

(com.example.dto)
。此外,您可能需要处理可选关联的空值,例如评级实体中的平台(如果它们在数据库中可为空)。

© www.soinside.com 2019 - 2024. All rights reserved.