Spring JPA使用@Query返回两个DB2 TIMESTAMP值之间的数据

pkmbmrz7  于 2022-11-07  发布在  DB2
关注(0)|答案(3)|浏览(170)

我正在编写一个Springboot JPARESTAPI,它与DB2数据库进行通信,并且应该查询一个包含TIMESTAMP字段的表。
使用SQL,过滤两个TIMESTAMP之间的行的DB2查询将如下所示,它将从我的测试数据中返回1条记录:

SELECT * FROM CARS WHERE SOLD_DATE BETWEEN '2020-01-01' AND '2022-01-01'

由于我使用的是SpringDataJPA,因此我定义了CarEntity,其中包含一个java.sql.Timestamp字段

@Entity
public class CarEntity {
   ....
   Timestamp soldDate;
   ...
   //getters and setters
}

我正在尝试检索数据,就像在上面的SQL查询。
为此,我在Postman中将开始和结束数据作为表示开始和结束日期的Long值通过如下URL传递

http://localhost:8080/cars/sold/1420070400/1640995200

这个端点访问我的控制器方法,该方法将Long转换为java.sql.Date,并将其传递给仓库,在仓库中,我使用@Query注解,如下所示:

@Repository
public interface CarRepository extends JpaRepository<CarEntity, Timestamp>{
    @Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between :startDate and :endDate") 
    List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);
}

但是,这不起作用,它没有返回任何数据,尽管我知道它应该返回1条记录。
但如果我像下面这样硬编码开始和结束日期,我会得到1条记录:

@Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between '2020-01-01' and '2022-01-01'") 
List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);

当然,问题是我硬编码了startDate和endDate,而不是使用传递到getCarsSoldBetween()方法中的startDate和endDate。

更新-1

感谢@HYUNJUN,我添加了几个更改:
1.我像以前一样在我的实体中使用java.sql.Timestamp,但是我的控制器、服务和仓库使用java.util.Date,而不是我最初使用的java.sql.Date
1.在我的www.example.com下面application.properties添加了能够查看SQL中传递了哪些参数(注意,这会引入明显的减速,因此仅用于调试目的):一个月一个月一个月一个月一个月
现在,当我转到DB2 Bench并发出以下查询时,我将返回2行,这是正确的:

SELECT * FROM MYSCHEMA.CARS WHERE SOLD_TIMESTAMP BETWEEN '2021-10-04 15:00:00' AND '2021-10-20 00:00:00';

// RETURNS 2 ROWS

但是,我的存储库查询如下所示:

@Repository
public interface CarRepository extends JpaRepository<CarEntity, Timestamp>{
    @Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between :startDate and :endDate") 
    List<CarEntity> getCarsSoldBetween(Date startDate, Date endDate);
}

,不返回任何内容,我希望返回2行,因为根据日志输出,开始日期和结束日期相同:

type.descriptor.sql.BasicBinder  binding parameter [1] as [TIMESTAMP] - [Mon Oct 04 15:00:00 PDT 2021]
type.descriptor.sql.BasicBinder  binding parameter [2] as [TIMESTAMP] - [Wed Oct 20 00:00:00 PDT 2021]

因此,我传递了相同的日期范围,并希望得到相同的结果,但这并没有发生

azpvetkf

azpvetkf1#

我最终得到了它与我的CarEntity使用java.sql.Timestamp工作,因为最初张贴,但这不会过滤数据正确,我会不断得到不同的记录从我的控制器与记录从SQL选择。
我发现,混合日期类型,就像我在上面使用java.sql.Datejava.sql.Timestampjava.util.Date的地方所做的那样,最有可能是造成这种情况的原因,我怀疑日期转换关闭,导致我的控制器返回错误的数据。
然后我读了这篇文章https://thorben-janssen.com/hibernate-jpa-date-and-time/,意识到即使我的DB2表使用TIMESTAMP,我也可以使用java.sql.Date
因此,我修改了我的控制器、服务、存储库和实体,以使用java.util.Date,而不是使用java.sql.Datejava.sql.Timestamp
这解决了我的问题。

8fsztsew

8fsztsew2#

我写的代码和你上面的代码几乎一样。但是我没有遇到你提到的问题。我把我的代码上传到下面。你为什么不把我的代码和你的代码比较一下呢?

package com.springboot.springbootinternals.db2;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class Db2Controller {

    private final CarRepository carRepository;

    @GetMapping("db2/{start-date}/{end-date}")
    public String db2(
        @PathVariable("start-date") Long startDate,
        @PathVariable("end-date") Long endDate
    ) {

        carRepository.save(Car.builder().date(new Timestamp(1420070401L * 1000)).build());

        Date start = new Date(TimeUnit.SECONDS.toMillis(startDate));
        Date end = new Date(TimeUnit.SECONDS.toMillis(endDate));
        List<Car> cars = carRepository.findAll(start, end);
        System.out.println(">>> " + cars);
        return "success";
    }
}

@Entity
@Builder
@NoArgsConstructor
@ToString
@AllArgsConstructor
class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Timestamp date;
}

@Repository
interface CarRepository extends JpaRepository<Car, Long> {

    @Query("select c from Car c where c.date between :startDate and :endDate")
    List<Car> findAll(Date startDate, Date endDate);
}

此外,将此选项放在applicaion.yml中,以检查是否将正确的值传递到SQL。

logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          descriptor:
            sql:
              BasicBinder: TRACE # show_parameter_value

就像这样。

3qpi33ja

3qpi33ja3#

您可以使用以下代码检索所需的结果

@Repository
public interface CarEntityRepository extends JpaRepository<CarEntity,Long> {

    @Query("SELECT c FROM CarEntity c WHERE c.carModel like %:model% and c.soldDate  > :start and  c.soldDate  < :end ")
    List<CarEntity> getCarsSoldBetween(@Param("model") String model, @Param("start") Date start, @Param("end") Date end);
}

相关问题