我正在开发一个带有公交时刻表的Web应用程序。我的任务是搜索一个时间表列表,其中有一个停止输入的用户。但是当我将查询写入数据库时,我得到一个白标签错误页面“ERROR:JOIN/ON的参数必须是boolean类型,而不是bigint类型”
There was an unexpected error (type=Internal Server Error, status=500).
JDBC exception executing SQL [SELECT DISTINCT c FROM schedules c JOIN routes r ON c.routes_id JOIN routes_stops rs on r.route_id JOIN stops s ON rs.stop_id WHERE s.name = ? and c.departure_time >= ? and c.departure_time < ?] [ERROR: argument of JOIN/ON must be type boolean, not type bigint Position: 53] [n/a]; SQL [n/a]
org.springframework.dao.InvalidDataAccessResourceUsageException: JDBC exception executing SQL [SELECT DISTINCT c FROM schedules c JOIN routes r ON c.routes_id JOIN routes_stops rs on r.route_id JOIN stops s ON rs.stop_id WHERE s.name = ? and c.departure_time >= ? and c.departure_time < ?] [ERROR: argument of JOIN/ON must be type boolean, not type bigint
Position: 53] [n/a]; SQL [n/a]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:256)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:229)
我的请求看起来像这样:
public interface ScheduleRepository extends JpaRepository<Schedule, Long> {
// more methods ...
@Query(value = "SELECT DISTINCT c FROM schedules c " +
"JOIN routes r ON c.routes_id " +
"JOIN routes_stops rs on r.route_id " +
"JOIN stops s ON rs.stop_id " +
"WHERE s.name = :stopName and c.departure_time >= :departureTime and c.departure_time < :endOfDay", nativeQuery = true)
List<Schedule> findAllByStopsAndTimeForSearch(@Param("stopName") String stopName,
@Param("departureTime")LocalDateTime departureTime,
@Param("endOfDay") LocalDateTime endOfDay);
}
服务接口:
public interface ScheduleService {
// more methods ...
List<Schedule> findAllByStopsAndTimeForSearchToday(String stopName);
List<Schedule> findAllByStopsAndTimeForSearchTomorrow(String stopName);
List<Schedule> findAllByStopsAndTimeForSearchAfterTomorrow(String stopName);
}
服务实施:
@Service
public class ScheduleServiceImpl implements ScheduleService {
private ScheduleRepository repository;
@Autowired
public ScheduleServiceImpl(ScheduleRepository repository) {
this.repository = repository;
}
// more methods ...
@Override
public List<Schedule> findAllByStopsAndTimeForSearchToday(String stopName) {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime endOfDay = currentDateTime.toLocalDate().plusDays(1).atTime(LocalTime.MIDNIGHT);
List<Schedule> scheduleToday = repository.findAllByStopsAndTimeForSearch(stopName, currentDateTime, endOfDay);
return scheduleToday;
}
@Override
public List<Schedule> findAllByStopsAndTimeForSearchTomorrow(String stopName) {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime startOfNextDay = currentDateTime.toLocalDate().plusDays(1).atTime(LocalTime.MIDNIGHT);
LocalDateTime endOfNextDay = startOfNextDay.toLocalDate().plusDays(1).atTime(LocalTime.MIDNIGHT);
List<Schedule> scheduleTomorrow = repository.findAllByStopsAndTimeForSearch(stopName, startOfNextDay, endOfNextDay);
return scheduleTomorrow;
}
@Override
public List<Schedule> findAllByStopsAndTimeForSearchAfterTomorrow(String stopName) {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime startOfNextDay = currentDateTime.toLocalDate().plusDays(2).atTime(LocalTime.MIDNIGHT);
LocalDateTime endOfNextDay = startOfNextDay.toLocalDate().plusDays(2).atTime(LocalTime.MIDNIGHT);
List<Schedule> scheduleAfterTomorrow = repository.findAllByStopsAndTimeForSearch(stopName, startOfNextDay, endOfNextDay);
return scheduleAfterTomorrow;
}
}
控制器:
@Controller
public class BusController {
private ScheduleService scheduleService;
@Autowired
public BusController(ScheduleService scheduleService) {
this.scheduleService = scheduleService;
}
// more methods ...
@GetMapping("/schedule/search")
public String searchBuses(@Valid @ModelAttribute("search") SearchDto search,
BindingResult bindingResult,
Model model){
if(bindingResult.hasErrors()){
LocalDateTime currentTime = LocalDateTime.now();
model.addAttribute("time", currentTime);
model.addAttribute("search", search);
return "buses-list";
}
LocalDateTime currentTime = LocalDateTime.now();
List<Schedule> scheduleToday = scheduleService.findAllByStopsAndTimeForSearchToday(search.getSearchLine());
List<Schedule> scheduleTomorrow = scheduleService.findAllByStopsAndTimeForSearchTomorrow(search.getSearchLine());
List<Schedule> scheduleAfterTomorrow = scheduleService.findAllByStopsAndTimeForSearchAfterTomorrow(search.getSearchLine());
model.addAttribute("time", currentTime);
model.addAttribute("scheduleToday", scheduleToday);
model.addAttribute("scheduleTomorrow", scheduleTomorrow);
model.addAttribute("scheduleAfterTomorrow", scheduleAfterTomorrow);
model.addAttribute("search", new SearchDto());
return "buses-list";
}
}
数据库表对象看起来像这样:
时间表:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "schedules")
public class Schedule {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "buses_id")
private Bus bus;
@ManyToOne
@JoinColumn(name = "routes_id")
private Route route;
private Double price;
private String accessibility;
private Integer seats;
private LocalDateTime arrivalTime;
private LocalDateTime departureTime;
}
路线:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "routes")
public class Route {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "route")
private List<Schedule> schedule;
@OneToMany(
mappedBy = "route",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<RoutesStops> routesStops;
}
停止:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "stops")
public class Stop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(
mappedBy = "stop",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<RoutesStops> routesStops;
}
RoutesStopsId:
@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class RoutesStopsId implements Serializable {
private Long routeId;
private Long stopId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RoutesStopsId that = (RoutesStopsId) o;
return Objects.equals(routeId, that.routeId) && Objects.equals(stopId, that.stopId);
}
@Override
public int hashCode() {
return Objects.hash(routeId, stopId);
}
}
路线停靠站:
@Entity
@Table(name = "routes_stops")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class RoutesStops {
@EmbeddedId
private RoutesStopsId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("routeId")
private Route route;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("stopId")
private Stop stop;
private Integer stopNumber;
private Double price;
private LocalTime arrivalTime;
private LocalTime departureTime;
}
公交车:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "buses")
public class Bus {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String licensePlate;
@OneToMany(mappedBy = "bus")
private List<Schedule> schedule;
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
}
公司名称:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "companies")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "company")
private List<Bus> bus;
}
我认为问题出在对数据库的请求的构造上,或者我没有正确地组织或链接DB表。
根据我读到的一个建议,我将请求更改为类似于存储库中的方法:
@Query("SELECT DISTINCT c FROM Schedule c " +
"JOIN Route r ON c.route " +
"JOIN RoutesStops rs on r.routesStops " +
"JOIN Stop s ON rs.stop " +
"WHERE s.name = :stopName and c.departureTime >= :departureTime and c.departureTime < :endOfDay")
List<Schedule> findAllByStopsAndTimeForSearch(@Param("stopName") String stopName,
@Param("departureTime")LocalDateTime departureTime,
@Param("endOfDay") LocalDateTime endOfDay);
但在那之后,我又犯了一个错误:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'busController' defined in file [/Users/artem/IdeaProjects/Bus Schedule Application/target/classes/com/busschedule/web/controller/BusController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'scheduleServiceImpl' defined in file [/Users/artem/IdeaProjects/Bus Schedule Application/target/classes/com/busschedule/web/service/impl/ScheduleServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'scheduleRepository' defined in com.busschedule.web.repository.ScheduleRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.List com.busschedule.web.repository.ScheduleRepository.findAllByStopsAndTimeForSearch(java.lang.String,java.time.LocalDateTime,java.time.LocalDateTime); Reason: Validation failed for query for method public abstract java.util.List com.busschedule.web.repository.ScheduleRepository.findAllByStopsAndTimeForSearch(java.lang.String,java.time.LocalDateTime,java.time.LocalDateTime)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-6.0.11.jar:6.0.11]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:245) ~[spring-beans-6.0.11.jar:6.0.11]
现在我很困惑,不明白哪个错误更好纠正,朝哪个方向前进
1条答案
按热度按时间yvt65v4c1#
因为你使用的是
nativeQuery
(而不是JPQL/HQL),你需要正确地指定连接表达式: