Я создал два @Entities (Player, Tournament), которые связаны отношениями @Many-To-Many.
@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;
// ...
}
@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; }
// ...
}
Теперь я хочу получить все турниры, в которых участвовал конкретный игрок:
@Service
public class TournamentService {
@Autowired
private TournamentRepository repo;
public List<Tournament> findTournamentsByPlayerId(Long id) {
return repo.findTournamentsByPlayerId(id);
}
}
@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', когда я навожу курсор на название стола.
Что я делаю не так? Спасибо!
Это не работает ни так: я получил эту ошибку: Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'playerId' found for type 'Tournament'
Попробуйте использовать приведенный ниже код в вашем турнире.java
Введите код сюда:
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "PlayerTournament",
joinColumns = @JoinColumn(name = "tournament_id"),
inverseJoinColumns = @JoinColumn(name = "player_id"))
private Set<Player> players= new HashSet<>();
Все еще незамеченный
Вам не нужно @Query anatotion, если вы хотите проводить турниры по playerId. Spring Boot сделает это за вас.
@Repository
public interface TournamentRepository extends CrudRepository<Tournament, Long> {
List<Tournament> findTournamentsByPlayersId(Long playerId);
}
Это работает нормально! Но есть ли способ сделать это с помощью @Query?
Проблема в том, что вы путаете 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 в запросе?
@EmanuelePapa Это была опечатка. Я починил это.
Почему вы не используете напрямую данные Spring для прямого поиска вместо использования @Query ; Вы можете использовать что-то вроде List<Tournament> findTournamentsByPlayerId(Long id), для которого IDE предложит хороший синтаксис. См. пример здесь docs.spring.io/spring-data/jpa/docs/current/reference/html