Java 如何使用Spring数据JPA按日期和时间进行搜索?
我正在学习SpringDataJPA,我有一个应用程序,我尝试按日期搜索,但它不起作用 问题是当我试图在数据库中搜索日期时。我有一个MySQL数据库,如果我直接在MySQL工作台中搜索,它是有效的,但是如果我尝试从我的应用程序中搜索,它是无效的。我什么也得不到。如果我尝试搜索其他东西,我会得到结果。所以我确信当我试图寻找一个约会的时候会有问题。我不知道是什么问题。任何反馈都将不胜感激。谢谢大家! 更新 一开始,这个应用程序运行得非常好。我可以在数据库中按日期搜索。在那之后,我添加了Spring安全性和更多的实体,在那之后,我无法在数据库中按日期搜索,并且我没有接触搜索方法。这很奇怪。现在我有了第一个版本的应用程序,它可以工作,而第二个版本不工作。并且两个应用程序都以相同的db实例为目标。但问题是,只有当我尝试按日期搜索时,如果我按出发城市和到达城市搜索,它才能正常工作,当我尝试按日期搜索时,我什么也得不到,列表是空的 以下是无法运行的应用程序版本。这是Github链接-> 下面是另一个运行完美的应用程序: 实体: 抽象实体类:Java 如何使用Spring数据JPA按日期和时间进行搜索?,java,spring-boot,date,spring-data-jpa,Java,Spring Boot,Date,Spring Data Jpa,我正在学习SpringDataJPA,我有一个应用程序,我尝试按日期搜索,但它不起作用 问题是当我试图在数据库中搜索日期时。我有一个MySQL数据库,如果我直接在MySQL工作台中搜索,它是有效的,但是如果我尝试从我的应用程序中搜索,它是无效的。我什么也得不到。如果我尝试搜索其他东西,我会得到结果。所以我确信当我试图寻找一个约会的时候会有问题。我不知道是什么问题。任何反馈都将不胜感激。谢谢大家! 更新 一开始,这个应用程序运行得非常好。我可以在数据库中按日期搜索。在那之后,我添加了Spring安
package com.dgs.flightreservationapp.entities;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
飞行等级:
package com.dgs.flightreservationapp.entities;
import java.sql.Timestamp;
import java.time.LocalDate;
import javax.persistence.Entity;
@Entity
public class Flight extends AbstractEntity {
private String flightNumber;
private String operatingAirlines;
private String departureCity;
private String arrivalCity;
private LocalDate dateOfDeparture;
private Timestamp estimatedDepartureTime;
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getOperatingAirlines() {
return operatingAirlines;
}
public void setOperatingAirlines(String operatingAirlines) {
this.operatingAirlines = operatingAirlines;
}
public String getDepartureCity() {
return departureCity;
}
public void setDepartureCity(String departureCity) {
this.departureCity = departureCity;
}
public String getArrivalCity() {
return arrivalCity;
}
public void setArrivalCity(String arrivalCity) {
this.arrivalCity = arrivalCity;
}
public LocalDate getDateOfDeparture() {
return dateOfDeparture;
}
public void setDateOfDeparture(LocalDate dateOfDeparture) {
this.dateOfDeparture = dateOfDeparture;
}
public Timestamp getEstimatedDepartureTime() {
return estimatedDepartureTime;
}
public void setEstimatedDepartureTime(Timestamp estimatedDepartureTime) {
this.estimatedDepartureTime = estimatedDepartureTime;
}
}
乘客等级:
package com.dgs.flightreservationapp.entities;
import javax.persistence.Entity;
@Entity
public class Passenger extends AbstractEntity {
private String firstName;
private String lastName;
private String middleName;
private String email;
private String phone;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
预订类别:
package com.dgs.flightreservationapp.entities;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
@Entity
public class Reservation extends AbstractEntity {
private Boolean checkedIn;
private int numberOfBags;
@OneToOne
private Passenger passenger;
@OneToOne
private Flight flight;
public Boolean getCheckedIn() {
return checkedIn;
}
public void setCheckedIn(Boolean checkedIn) {
this.checkedIn = checkedIn;
}
public int getNumberOfBags() {
return numberOfBags;
}
public void setNumberOfBags(int numberOfBags) {
this.numberOfBags = numberOfBags;
}
public Passenger getPassenger() {
return passenger;
}
public void setPassenger(Passenger passenger) {
this.passenger = passenger;
}
public Flight getFlight() {
return flight;
}
public void setFlight(Flight flight) {
this.flight = flight;
}
}
角色类别:
package com.dgs.flightreservationapp.entities;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
@Entity
public class Role extends AbstractEntity {
private String name;
@ManyToMany(fetch=FetchType.EAGER,
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
@JoinTable(
name="user_role",
joinColumns=@JoinColumn(name="role_id"),
inverseJoinColumns=@JoinColumn(name="user_id")
)
private Set<User> users;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
FlightRepository:
package com.dgs.flightreservationapp.repos;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.dgs.flightreservationapp.entities.Flight;
public interface FlightRepository extends JpaRepository<Flight, Long> {
// @Query("from Flight where departureCity=:departureCity and arrivalCity=:arrivalCity and dateOfDeparture=:dateOfDeparture")
// List<Flight> findFlights(@Param("departureCity") String from,
// @Param("arrivalCity") String to,
// @Param("dateOfDeparture") LocalDate departureDate);
List<Flight> findByDepartureCityAndArrivalCityAndDateOfDeparture(String from, String to, LocalDate departureDate);
}
package com.dgs.flightreservationapp.repos;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dgs.flightreservationapp.entities.User;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
UserDetailsServiceImpl:
package com.dgs.flightreservationapp.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.dgs.flightreservationapp.entities.User;
import com.dgs.flightreservationapp.repos.UserRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found for email " + username);
}
return new UserPrincipal(user);
}
}
用户主体
package com.dgs.flightreservationapp.security;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.dgs.flightreservationapp.entities.Role;
import com.dgs.flightreservationapp.entities.User;
public class UserPrincipal implements UserDetails {
private User user;
public UserPrincipal(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return grantedAuthorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
MySQL架构:
CREATE DATABASE reservation
USE reservation
CREATE TABLE user
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20),
last_name VARCHAR(20),
email VARCHAR(20),
password VARCHAR(256),
PRIMARY KEY (id),
UNIQUE KEY (email)
);
CREATE TABLE flight
(
id INT NOT NULL AUTO_INCREMENT,
flight_number VARCHAR(20) NOT NULL,
operating_airlines VARCHAR(20) NOT NULL,
departure_city VARCHAR(20) NOT NULL,
arrival_city VARCHAR(20) NOT NULL,
date_of_departure DATE NOT NULL,
estimated_departure_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id);
)
CREATE TABLE passenger
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(256),
last_name VARCHAR(256),
middle_name VARCHAR(256),
email VARCHAR(50),
phone VARCHAR(10),
PRIMARY KEY (id)
);
CREATE TABLE reservation
(
id INT NOT NULL AUTO_INCREMENT,
checked_in TINYINT(1),
number_of_bags INT,
passenger_id INT,
flight_id INT,
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (passenger_id) REFERENCES passenger(id) ON DELETE CASCADE,
FOREIGN KEY (flight_id) REFERENCES flight(id)
);
CREATE TABLE role
(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20),
PRIMARY KEY (id)
);
create table user_role(
user_id int,
role_id int,
FOREIGN KEY (user_id)
REFERENCES user(id),
FOREIGN KEY (role_id)
REFERENCES role(id)
);
insert into flight values(1,'AA1','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 03:14:07');
insert into flight values(2,'AA2','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 05:14:07');
insert into flight values(3,'AA3','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 06:14:07');
insert into flight values(4,'SW1','South West','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 07:14:07');
insert into flight values(5,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 10:14:07');
insert into flight values(6,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 10:14:07');
insert into flight values(7,'SW1','South West','AUS',
'NYC',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 07:14:07');
insert into flight values(8,'SW2','South West','AUS',
'NYC',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 08:14:07');
insert into flight values(9,'SW3','South West','NYC',
'DAL',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 10:14:07');
insert into flight values(10,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 10:14:07');
insert into user values(1,'John','Doe','john@gmail.com',
'$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K');
您可以使用登录john@gmail.com密码是fun123
如果您想测试另一个工作正常的应用程序,需要在db中添加以下内容:
insert into user values(2,'Tom','Abc','tom@gmail.com','fun123');
然后使用登录tom@gmail.comfun123和Fin Flights将AUS、NYC和2018年5月2日放在一起,您将获得此应用程序的结果。但是对于另一个应用程序,你不会得到任何结果。这很奇怪 我认为您需要使用
@Temporal(TemporalType.date)
像
MySql
Date
type,因此您在Flight
实体上使用的Date
类型及其时间部分可能会中断您的查询。尝试用Java8日期/时间API中的LocalDate
替换Date
,该API也只包含日期,不包含任何时间信息
private LocalDate dateOfDeparture;
&
除此之外,对于这样一个简单的逻辑,您不需要使用
@Query
。您可以使用它,这是SpringDataJPA的一个很好的特性
public interface FlightRepository extends JpaRepository<Flight, Long> {
List<Flight> findByDepartureCityAndArrivalCityAndDateOfDeparture(String from, String to, LocalDate departureDate);
}
存储库工作正常,我无法运行其他端点等,但查询/架构等没有问题。问题的发生是因为数据转换 com.mysql.cj.jdbc.ClientPreparedStatement:选择flight0.id作为id1\u 0\u,flight0.arrival\u city作为arrival\u 2\u 0\u,flight0.date\u作为出发日期,flight0\u作为出发城市,flight0\u。预计出发时间为Estimated5\u 0,flight0\u。航班号为flight6\u 0\u,航班0。运营航空公司从航班0开始运营,航班0。出发地为澳大利亚城市,航班0。到达地为纽约市,航班0。出发日期为2018-02-04 18:30:00.0 正如您所看到的,日期没有以正确的格式转换,因此我们推出了自己的转换器来解决这个问题 flightreservationapp/converters/LocalDateAttributeConverter.java
package com.dgs.flightreservationapp.converters;
导入javax.persistence.AttributeConverter;
导入javax.persistence.Converter;
导入java.time.LocalDate;
@转换器(自动应用=真)
公共类LocalDateAttributeConverter实现AttributeConverter{
@凌驾
公共字符串convertToDatabaseColumn(LocalDate locDate){
返回locDate==null?null:locDate.toString();
}
@凌驾
公共LocalDate convertToEntityAttribute(字符串sqlDate){
返回sqlDate==null?null:LocalDate.parse(sqlDate);
}
}
添加此文件后,您将开始获得结果
你还有其他选择。向JPA方法添加注释
列出查找到的DbyDepartureCity和DarRivalcityandDateofDeparture(字符串从,字符串到,
@DateTimeFormat(iso=DateTimeFormat.iso.DATE)
本地日期(离开日期);
然后,您需要确保将时区也设置为UTC
公共类FlightReservationAppApplication{
公共静态void main(字符串[]args){
run(FlightReservationAppApplication.class,args);
}
@施工后
void init(){
TimeZone.setDefault(TimeZone.getTimeZone(“UTC”));
}
}
另一种选择是在pom.xml
org.hibernate
hibernate-java8
5.1.0.1最终版本
以及设置时区
公共类FlightReservationAppApplication{
公共静态void main(字符串[]args){
run(FlightReservationAppApplication.class,args);
}
@施工后
void init(){
TimeZone.setDefault(TimeZone.getTimeZone(“UTC”));
}
}
在您的非工作存储库()中,您在应用程序中有此附加配置。属性
:
spring.datasource.url=jdbc:mysql://localhost:3306/reservation?useSSL=false&serverTimezone=UTC
部分serverTimezone=UTC
导致您的输入日期与数据库中的日期不匹配=>错误结果
如果客户端应用程序和mysql服务器的时区不同,则会出现一个已知的错误:
所以现在,要么将两者设置为相同的时区,要么避免在Java中使用本地***类我也这样做了,但什么都没有,列表为空。db日期格式和输入格式相同吗@gabydb格式为日期,输入格式为日期。我在添加了Spring安全性之后遇到了这个问题,在此之前它工作得很好。只需记录日志
CREATE DATABASE reservation
USE reservation
CREATE TABLE user
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20),
last_name VARCHAR(20),
email VARCHAR(20),
password VARCHAR(256),
PRIMARY KEY (id),
UNIQUE KEY (email)
);
CREATE TABLE flight
(
id INT NOT NULL AUTO_INCREMENT,
flight_number VARCHAR(20) NOT NULL,
operating_airlines VARCHAR(20) NOT NULL,
departure_city VARCHAR(20) NOT NULL,
arrival_city VARCHAR(20) NOT NULL,
date_of_departure DATE NOT NULL,
estimated_departure_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id);
)
CREATE TABLE passenger
(
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(256),
last_name VARCHAR(256),
middle_name VARCHAR(256),
email VARCHAR(50),
phone VARCHAR(10),
PRIMARY KEY (id)
);
CREATE TABLE reservation
(
id INT NOT NULL AUTO_INCREMENT,
checked_in TINYINT(1),
number_of_bags INT,
passenger_id INT,
flight_id INT,
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (passenger_id) REFERENCES passenger(id) ON DELETE CASCADE,
FOREIGN KEY (flight_id) REFERENCES flight(id)
);
CREATE TABLE role
(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20),
PRIMARY KEY (id)
);
create table user_role(
user_id int,
role_id int,
FOREIGN KEY (user_id)
REFERENCES user(id),
FOREIGN KEY (role_id)
REFERENCES role(id)
);
insert into flight values(1,'AA1','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 03:14:07');
insert into flight values(2,'AA2','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 05:14:07');
insert into flight values(3,'AA3','American Airlines','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 06:14:07');
insert into flight values(4,'SW1','South West','AUS',
'NYC',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 07:14:07');
insert into flight values(5,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 10:14:07');
insert into flight values(6,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-05-2018', '%m-%d-%Y'),'2018-02-05 10:14:07');
insert into flight values(7,'SW1','South West','AUS',
'NYC',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 07:14:07');
insert into flight values(8,'SW2','South West','AUS',
'NYC',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 08:14:07');
insert into flight values(9,'SW3','South West','NYC',
'DAL',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 10:14:07');
insert into flight values(10,'UA1','United Airlines','NYC',
'DAL',STR_TO_DATE('02-06-2018', '%m-%d-%Y'),'2018-02-06 10:14:07');
insert into user values(1,'John','Doe','john@gmail.com',
'$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K');
insert into user values(2,'Tom','Abc','tom@gmail.com','fun123');
@Entity
public class Flight extends AbstractEntity {
private String flightNumber;
private String operatingAirlines;
private String departureCity;
private String arrivalCity;
@Temporal(TemporalType.DATE)
private Date dateOfDeparture;
private Timestamp estimatedDepartureTime;
}
private LocalDate dateOfDeparture;
@Param("dateOfDeparture") LocalDate departureDate
public interface FlightRepository extends JpaRepository<Flight, Long> {
List<Flight> findByDepartureCityAndArrivalCityAndDateOfDeparture(String from, String to, LocalDate departureDate);
}
@PostMapping("/processFlights")
public String processFlights(..) {
List<Flight> flights = flightRepository.findByDepartureCityAndArrivalCityAndDateOfDeparture(from, to, departureDate);
modelMap.addAttribute("flights", flights);
return "displayFlights";
}
public interface FlightRepository extends JpaRepository<Flight, Long> {
List<Flight> findByDepartureCityAndArrivalCityAndDateOfDeparture(String from, String to, LocalDate departureDate);
// you can use this from your controller
default List<Flight> findFlights(String from, String to, LocalDate departureDate) {
return findByDepartureCityAndArrivalCityAndDateOfDeparture(from, to, departureDate);
}
}
@SpringBootApplication
public class FlightReservationAppApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(FlightReservationAppApplication.class, args);
FlightRepository flightRepository = run.getBean(FlightRepository.class);
Flight flight = new Flight();
flight.setDepartureCity("AUS");
flight.setArrivalCity("NYC");
flight.setDateOfDeparture(LocalDate.of(2018, 1, 5));
flightRepository.save(flight);
List<Flight> list = flightRepository.findByDepartureCityAndArrivalCityAndDateOfDeparture("AUS", "NYC", LocalDate.of(2018, 1, 5));
System.out.println(list.size()); // prints out 1
}
}
spring.datasource.url=jdbc:mysql://localhost:3306/reservation?useSSL=false&serverTimezone=UTC