SpringBoot: @Query не обнаруживает таблицу «многие ко многим»

Я создал два @Entities (Player, Tournament), которые связаны отношениями @Many-To-Many.

Player.java

@Entity
@Table
public class Player {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(updatable = false)
    private String email;
    @Column
    private String name;

    // ...
    
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "PlayerTournament",
               joinColumns = @JoinColumn(name = "player_id"),
               inverseJoinColumns = @JoinColumn(name = "tournament_id"))
    private Set<Tournament> tournaments;

    // ...

}

Турнир.java

@Entity
@Table
public class Tournament{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(updatable = false)
    private String name;

    // ...

    @ManyToMany(mappedBy = "tournaments")
    private Set<Player> players= new HashSet<>();

    public Set<Player> getPlayers() { return players; }

    public void setPlayers(Set<Player> players) { this.players = players; }


    // ...

}

Теперь я хочу получить все турниры, в которых участвовал конкретный игрок:

TournamentService.java

@Service
public class TournamentService {

    @Autowired
    private TournamentRepository repo;

    public List<Tournament> findTournamentsByPlayerId(Long id) {
        return repo.findTournamentsByPlayerId(id);
    }
}

TournamentRepository.java

@Repository
public interface TournamentRepository extends CrudRepository<Tournament, Long> {

    @Query("select t from Tournament t join PlayerTournament pt on t.id = pt.tournament_id where pt.player_id = :id")
    List<Tournament> findTournamentsByPlayerId(@Param("id") Long id);
}

Но этот код не работает. Когда я пытаюсь запустить приложение, я получаю эту ошибку: Caused by: java.lang.IllegalArgumentException: Could not resolve entity reference: PlayerTournament

IDEE говорит, что это Cannot resolve symbol 'PlayerTournament', когда я навожу курсор на название стола.

Что я делаю не так? Спасибо!

Почему вы не используете напрямую данные Spring для прямого поиска вместо использования @Query ; Вы можете использовать что-то вроде List<Tournament> findTournamentsByPlayerId(Long id), для которого IDE предложит хороший синтаксис. См. пример здесь docs.spring.io/spring-data/jpa/docs/current/reference/html

flyordie 11.01.2023 00:02

Это не работает ни так: я получил эту ошибку: Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'playerId' found for type 'Tournament'

Emanuele Papa 11.01.2023 00:14
Лучшая компания по разработке спортивных приложений
Лучшая компания по разработке спортивных приложений
Ищете лучшую компанию по разработке спортивных приложений? Этот список, несомненно, облегчит вашу работу!
Blibli Automation Journey - Как захватить сетевой трафик с помощью утилиты HAR в Selenium 4
Blibli Automation Journey - Как захватить сетевой трафик с помощью утилиты HAR в Selenium 4
Если вы являетесь веб-разработчиком или тестировщиком, вы можете быть знакомы с Selenium, популярным инструментом для автоматизации работы...
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Что такое Java 8 Streams API? Java 8 Stream API
Деревья поиска (Алгоритм4 Заметки к учебнику)
Деревья поиска (Алгоритм4 Заметки к учебнику)
(1) Двоичные деревья поиска: среднее lgN, наихудшее N для вставки и поиска.
0
2
76
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Попробуйте использовать приведенный ниже код в вашем турнире.java

Введите код сюда:

   @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "PlayerTournament",
               joinColumns = @JoinColumn(name = "tournament_id"),
               inverseJoinColumns = @JoinColumn(name = "player_id"))
    private Set<Player> players= new HashSet<>();

Все еще незамеченный

Emanuele Papa 11.01.2023 09:33

Вам не нужно @Query anatotion, если вы хотите проводить турниры по playerId. Spring Boot сделает это за вас.

@Repository
public interface TournamentRepository extends CrudRepository<Tournament, Long> {

    List<Tournament> findTournamentsByPlayersId(Long playerId);
}

Это работает нормально! Но есть ли способ сделать это с помощью @Query?

Emanuele Papa 11.01.2023 09:50
Ответ принят как подходящий

Проблема в том, что вы путаете JPA/JPQL и SQL.

Поскольку вы не указали nativeQuery=true в аннотации @Query, запрос считается запросом JPQL. Но JPQL работает на уровне сущностей и не знает о (отображении) таблиц.

Правильный JPQL-запрос должен выглядеть так:

select t from Tournament t where t.players.id = :id

Конечно, вы можете остаться с текущим запросом и использовать nativeQuery=true.

И, наконец, как правильно отмечает Фатхи, вам вообще не нужно указывать запрос и вы можете использовать вывод запроса с помощью метода вроде.

List<Tournament> findTournamentsByPlayersId(Long playerId);

Откуда pt в запросе?

Emanuele Papa 11.01.2023 09:37

@EmanuelePapa Это была опечатка. Я починил это.

Jens Schauder 11.01.2023 10:15

Другие вопросы по теме