我有一个带有实体玩家和评级的 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
您可以在 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)
。此外,您可能需要处理可选关联的空值,例如评级实体中的平台(如果它们在数据库中可为空)。