Spring Data JPA:返回空List而不是null

时间:2018-02-28 14:34:56

标签: hibernate jpa spring-data jpanel spring-data-jpa

我有一个基本的SpringBoot应用程序。使用Spring Initializer,JPA,嵌入式Tomcat,Thymeleaf模板引擎和包作为可执行的JAR文件。 我在从

扩展的存储库中定义了此方法
CrudRepository<HotelPrice, Long>, PagingAndSortingRepository<HotelPrice, Long> {

这是方法

List<HotelPrice> getByHotelAndUpdateDateGreaterThan (Hotel hotel, Date date, PageRequest pageRequest);

和服务:

public List<HotelPrice> getMonthlyMinPriceDate(Hotel hotel) {
        return hotelPriceRepository.getByHotelAndUpdateDateGreaterThan
                (hotel, DateUtils.monthlyDate(), new PageRequest(1, 1,new Sort(Sort.Direction.DESC, "price")));
    }

但是当我运行Junit测试时,我收到了这个错误:

 java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at org.springframework.data.jpa.repository.query.CriteriaQueryParameterBinder.bind(CriteriaQueryParameterBinder.java:65)
at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:101)
at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:161)
at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:152)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.invokeBinding(PartTreeJpaQuery.java:236)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:157)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:86)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:190)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:123)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:87)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:499)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy118.getByHotelAndUpdateDateGreaterThan(Unknown Source)
at com.booking.backend.service.HotelPriceService.getWeeklyMinPriceDate(HotelPriceService.java:85)
at com.booking.backend.service.HotelPriceService$$FastClassBySpringCGLIB$$cabd5c58.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
at com.booking.backend.service.HotelPriceService$$EnhancerBySpringCGLIB$$9dd8e53b.getWeeklyMinPriceDate(<generated>)
at com.booking.HotelPriceServiceTests.testGetWeeklyMaxPriceDate(HotelPriceServiceTests.java:125)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)Hotel
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)

可以返回空列表而不是null ????

我也设置了应用程序。财产spring.jpa.properties.hibernate.format_sql=true

但是我没有在控制台中看到任何sql

@Entity
@Table(name="t_Hotel_price")
public class HotelPrice implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public HotelPrice() {
    }


    public HotelPrice(Hotel Hotel) {
        this.Hotel = Hotel;
    }

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


    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "Hotel_id")
    Hotel Hotel;

    float price;

    @Column(name = "update_date")
    private Date updateDate;

    public Hotel getHotel() {
        return Hotel;
    }

    public void setHotel(Hotel Hotel) {
        this.Hotel = Hotel;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }



    public Long getId() {
        return id;
    }


    public void setId(Long id) {
        this.id = id;
    }


    public Date getUpdateDate() {
        return updateDate;
    }


    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }


    @Override
    public String toString() {
        return "HotelPrice [Hotel=" + Hotel + ", price=" + price + ", updateDate=" + updateDate + "]";
    }
}

@Entity
@Table(name="t_Hotel")
public class Hotel  implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

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

    private String HotelId;

    private String symbol;

    private float histMaxPrice;

    private int numMaxPriceEvents=0;

    @Column(name = "update_date")
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    private LocalDateTime histMaxPriceDate;

    @OneToMany(mappedBy="Hotel", fetch=FetchType.LAZY, orphanRemoval=true)
    private List<HotelDailyPrice> dailyPrice;

    @OneToMany(mappedBy="Hotel", fetch=FetchType.LAZY, orphanRemoval=true)
    private List<HotelPrice> price;

    @OneToMany(mappedBy="Hotel", fetch=FetchType.LAZY, orphanRemoval=true)
    private List<HotelPriceSummary> summary;


    public Hotel() {
        super();
    }

    public Hotel(String HotelId) {
        super();
        this.HotelId = HotelId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getHotelId() {
        return HotelId;
    }

    public void setHotelId(String HotelId) {
        this.HotelId = HotelId;
    }

    public float getHistMaxPrice() {
        return histMaxPrice;
    }

    public void setHistMaxPrice(float histMaxPrice) {
        this.histMaxPrice = histMaxPrice;
    }

    public LocalDateTime getHistMaxPriceDate() {
        return histMaxPriceDate;
    }

    public void setHistMaxPriceDate(LocalDateTime histMaxPriceDate) {
        this.histMaxPriceDate = histMaxPriceDate;
    }

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((HotelId == null) ? 0 : HotelId.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Hotel other = (Hotel) obj;
        if (HotelId == null) {
            if (other.HotelId != null)
                return false;
        } else if (!HotelId.equals(other.HotelId))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Hotel [id=" + id + ", HotelId=" + HotelId + ", histMaxPrice=" + histMaxPrice
                + ", histMaxPriceDate=" + histMaxPriceDate + "]";
    }

    public int getNumMaxPriceEvents() {
        return numMaxPriceEvents;
    }

    public void setNumMaxPriceEvents(int numMaxPriceEvents) {
        this.numMaxPriceEvents = numMaxPriceEvents;
    }

    public List<HotelDailyPrice> getDailyPrice() {
        return dailyPrice;
    }

    public void setDailyPrice(List<HotelDailyPrice> dailyPrice) {
        this.dailyPrice = dailyPrice;
    }

    public List<HotelPrice> getPrice() {
        return price;
    }

    public void setPrice(List<HotelPrice> price) {
        this.price = price;
    }

    public List<HotelPriceSummary> getSummary() {
        return summary;
    }

    public void setSummary(List<HotelPriceSummary> summary) {
        this.summary = summary;
    }
}

我也尝试使用Page<HotelPrice>,但后来我收到了错误:

Paging query needs to have a Pageable parameter!

这是函数DateUtils.monthlyDate()

LocalDate now = LocalDate.now()。minusDays(numDaysToSubstract);         return Date.from(now.atStartOfDay(ZoneId.systemDefault())。toInstant());

2 个答案:

答案 0 :(得分:0)

我在问题中注意到一些事情:(更新答案)

  1. 无需延伸CrudRepository<HotelPrice, Long>, PagingAndSortingRepository<HotelPrice, Long>PagingAndSortingRepository<HotelPrice, Long>在内部扩展CrudRepository<HotelPrice, Long>
  2. 您只能传递Hotel(id)的主键,而不是传递整个Hotel对象。下面给出了它的语法: Page<HotelPrice> getByHotelIdAndUpdateDateGreaterThan (Long id, Date date, Pageable pageable);。您可以从服务中发送PageRequest 但是你必须在Repository中有Pageable
  3. 当您使用分页时,您无法获得List<HotelPrice>的响应,而不是您将获得Page<HotelPrice>对象。要提取List<HotelPrice>,请使用以下内容: List<HotelPrice> hotelPrice = hotelPricePage.get().getContent();

答案 1 :(得分:0)

你应该检查两件事:

  1. DateUtils.monthlyDate()返回的方法是什么?它与您的存储库方法Date中的Date是否相同getByHotelAndUpdateDateGreaterThan (Hotel hotel, Date date, PageRequest pageRequest)
  2. 您真的希望页码一个,而不是第一页,它位于索引零?您可以在spring's docs for the PageRequest检查页面索引从零开始