Search code examples
javahibernatejpaspring-data-jpa

JPA many to one query retrieves too many fields


I have the same model on Java JPA:

@Entity
@Getter
@NoArgsConstructor
@Table(name = "review")
public class Review {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "game_id", referencedColumnName = "id")
    private Game game;

    @Column(name = "review_text", length = 1000)
    private String review_text;

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

    @Column(name = "likes")
    private Integer likes;

    @Column(name = "rating")
    private Integer rating;

    @Column(name = "createdAt")
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;

And I've done this endpoint:

@GetMapping("/ofgame/{gameId}")
public List<Review> getReviewsByGame(@PathVariable Integer gameId) {
    List<Review> reviews = new ArrayList<>();
    if (this.gameRepository.findById(gameId).isPresent()) {
        reviews = this.reviewRepository.findAllByGameId(gameId);
    }
    return reviews;
}

Being the method of the repository the next one:

List<Review> findAllByGameId(Integer gameId);

But my problem is that the query is returning all the fields from Game and User (including encoded passwords) when I thought only the user_id and game_id were going to be returned.

Did I understood something wrong about the JPA mapping? Or there is simply something I didn't add?


Solution

  • I finally got it, it was primarly because a misunderstanding of the JPA mapping but what it finally was a solution was creating a DTO (Data Transfer Object) with the exact fields I wanted and then change the custom query.

    DTO for my Review entity:

    @Getter
    public class ReviewDTO {
        private Integer id;
        private Integer userId;
        private Integer gameId;
        private String review_text;
        private String summary;
        private Integer likes;
        private Integer rating;
        private Date createdAt;
    
        public ReviewDTO(Integer id, Integer userId, Integer gameId, String reviewText, String summary, Integer likes, Integer rating, Date createdAt) {
            this.id = id;
            this.userId = userId;
            this.gameId = gameId;
            this.review_text = reviewText;
            this.summary = summary;
            this.likes = likes;
            this.rating = rating;
            this.createdAt = createdAt;
        }
    }
    

    Review repository with new query:

    @Repository
    public interface ReviewRepository extends JpaRepository<Review, Integer> {
        @Query("SELECT new com.lobby.app.model.ReviewDTO(r.id, r.user.id, r.game.id, r.review_text, r.summary, r.likes, r.rating, r.createdAt) " +
                "FROM Review r WHERE r.game.id = :gameId")
        List<ReviewDTO> findReviewsByGameId(@Param("gameId") Integer gameId);
    }