Проблема с запросом сущностей с набором сущностей в Spring Boot @Query - PullRequest
2 голосов
/ 01 августа 2020

Я хочу иметь Spring Boot @Query в JpaRepository, который возвращает мне объекты с набором других объектов. Я знаю, что могу использовать метод findAll(), а затем брать только те строки, которые мне интересны, но я думаю, что это намного медленнее. Проблема в том, что мой объект Booster содержит Set других объектов Boost, и когда я пытаюсь запросить его, я получаю сообщение об ошибке. Итак, это мой Query:

    @Query( "select new app.model.Booster(" +
            "   B.id, " +
            "   B.active, " +
            "   B.games, " +
            "   B.ownerAccount, " +
            "   B.boosts, " +
            "   B.boosterNickname, " +
            "   B.additionalInformation) " +
            "from " +
            "   Booster B " +
            "   left join Boost Bo on B.id = Bo.boostingAccount.id " +
            "where " +
            "   B.games like %?1% " +
            "   and Bo.finished = true " +
            "group by " +
            "   B.id")
    List<Booster> findBoostersForOverview(String game);

Это мои классы сущностей:

@Data
@Entity(name = "Booster")
public class Booster {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private boolean active;
    private String games;
    @OneToOne(mappedBy = "boosterAccount", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Account ownerAccount;
    @OneToMany(mappedBy = "boostingAccount", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Boost> boosts;
    private String boosterNickname;
    private String additionalInformation;
@Data
@Entity(name = "Boost")
public class Boost {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id",nullable=false,unique=true)
    private long id;
    private Date dateCreated;
    private Date dateFinished;
    private Date dateLastModification;
    private boolean finished;
    private boolean paused;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "boosted_account_id", referencedColumnName = "id")
    private Account boostedAccount;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "boosting_account_id", referencedColumnName = "id")
    private Booster boostingAccount;
    @OneToMany(mappedBy = "boost", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Game> games;
    private String game;
    private String additionalInformation;
    private String server;

Это то, что показывает консоль:

Hibernate: 
    select
        booster0_.id as col_0_0_,
        booster0_.active as col_1_0_,
        booster0_.games as col_2_0_,
        booster0_.id as col_3_0_,
        . as col_4_0_,
        booster0_.booster_nickname as col_5_0_,
        booster0_.additional_information as col_6_0_ 
    from
        booster booster0_ 
    //HERE IS SOME MORE LOGS THAT ARE UNNECESSARY HERE

И это ошибка, которую я получаю:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '. as col_4_0_, booster0_.booster_nickname as col_5_0_, booster0_.additional_info' at line 1

Я знаю, что могу запросить без Set из Boost, а затем в другом запросе получить спецификацию c Boost s, но в моем приложении будет много SQL, и мой код превратится в спагетти. Есть ли простой способ решить мою проблему?

Ответы [ 2 ]

1 голос
/ 01 августа 2020

Можете ли вы добавить в свой репозиторий следующее без любой @Query аннотации и посмотреть?

    List<Booster> findByGamesLikeAndBoostsFinishedIsTrue(String game);
0 голосов
/ 01 августа 2020

Проблема здесь в том, что вы используете GROUP BY. Когда вы используете Group By, вы должны использовать агрегатные функции (COUNT, MAX, MIN, SUM, AVG) для группировки набора результатов по одному или нескольким столбцам в столбце выбора. Агрегатные функции: обязательные при использовании функции GROUP BY.

В вашем случае, надеюсь, Group By не требуется. Измените свой код, как показано ниже.

@Query( "select new app.model.Booster(" +
        "   B.id, " +
        "   B.active, " +
        "   B.games, " +
        "   B.ownerAccount, " +
        "   B.boosts, " +
        "   B.boosterNickname, " +
        "   B.additionalInformation) " +
        "from " +
        "   Booster B " +
        "   left join Boost Bo on B.id = Bo.boostingAccount.id " +
        "where " +
        "   B.games like %?1% " +
        "   and Bo.finished = true")
List<Booster> findBoostersForOverview(String game);
...