如何使用 Spring Data JPA 对日期执行聚合操作?

How to perform aggregation operation using Spring Data JPA for a date?

场景:

在 Web 应用程序中,我正在从客户那里获取特定日期的订单。我必须按日期对这些订单执行聚合操作。例如,我想要 sum(quantity1),sum(quantity2),sum(quantity3),.... 2021 年 10 月 18 日,其中订单状态需要为 "PLACED"(两者都不是已取消或已交付)。

异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'adminController': Unsatisfied dependency expressed through field 'journeyFoodServiceImpl'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'journeyFoodServiceImpl' defined in file [C:\Users\TiaaUser\Desktop\AWS\journeyfood\target\classes\org\brahmakumaris\journeyfood\service\JourneyFoodServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'journeyFoodOrderRepository' defined in org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository.getOrdersByDateAndNotDisabled(java.lang.String,java.util.Date)!
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'journeyFoodServiceImpl' defined in file [C:\Users\TiaaUser\Desktop\AWS\journeyfood\target\classes\org\brahmakumaris\journeyfood\service\JourneyFoodServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'journeyFoodOrderRepository' defined in org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository.getOrdersByDateAndNotDisabled(java.lang.String,java.util.Date)!
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
    
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'journeyFoodOrderRepository' defined in org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository.getOrdersByDateAndNotDisabled(java.lang.String,java.util.Date)!
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
    ... 39 common frames omitted
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List org.brahmakumaris.journeyfood.repository.JourneyFoodOrderRepository.getOrdersByDateAndNotDisabled(java.lang.String,java.util.Date)!
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:93)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:63)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:76)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:56)
    ... 50 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "org.hibernate.type.Type.sqlTypes(org.hibernate.engine.spi.Mapping)" because "type" is null
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.determineJdbcTypeCode(StandardAnsiSqlAggregationFunctions.java:200)
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.getReturnType(StandardAnsiSqlAggregationFunctions.java:158)
    at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:430)
    at org.hibernate.hql.internal.ast.tree.AggregateNode.getDataType(AggregateNode.java:68)
    at org.hibernate.hql.internal.ast.tree.ConstructorNode.resolveConstructorArgumentTypes(ConstructorNode.java:158)
    at org.hibernate.hql.internal.ast.tree.ConstructorNode.prepare(ConstructorNode.java:133)
    ... 79 common frames omitted

我在执行操作时遇到上述异常。我尝试在 JourneyFoodOrderRepository 接口-

中创建下面提到的方法
@Repository
public interface JourneyFoodOrderRepository extends JpaRepository<JourneyFoodOrder, Long>{

    @Modifying
    @Query("SELECT new AggregateJourneyFoodOrder(SUM(head_count), SUM(bread), SUM(achar), SUM(jam) ,SUM(others), SUM(puri), SUM(roti), SUM(thepla), mealRetrievalDate)"
            + "  FROM JourneyFoodOrder j WHERE j.orderStatus=:orderStatus AND j.mealRetrievalDate = :mealRetrievalDate")
    List<AggregateJourneyFoodOrder> getOrdersByDateAndNotDisabled(@Param("orderStatus")String orderStatus, @Param("mealRetrievalDate")Date mealRetrievalDate);
}

JourneyFoodOrder.java

@Entity
public class JourneyFoodOrder{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long orderId;
    
    private Integer headCount;
    
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Date dateOfOrderPlaced;
    
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private LocalDate dateOfDeparture;
    
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private LocalDate mealRetrievalDate;
    
    @DateTimeFormat(pattern = "hh:mm:ss a")
    private LocalTime mealRetrievalTime;

    @ManyToOne
    private UserEntity user; 
    
    private Integer thepla;
    
    private Integer puri;
    
    private Integer roti;

    private Integer achar;
    
    private Integer jam;
    
    private Integer bread;
    
    private Integer others;
    
    private String orderStatus;

    //Getter setter and constructor
 }

汇总JourneyFoodOrder.java

@Entity
public class AggregateJourneyFoodOrder {
    private long totalHeadCount;
    private long totalBread;
    private long totalAchar;
    private long totalJam;
    private long totalOthers;
    private long totalPuri;
    private long totalRoti;
    private long totalThepla;
    @Id
    private LocalDate mealRetrievalDate;
    //Getters/setters/constructors
}

服务代码 JourneyFoodServiceImpl.java

@Transactional
@Service
public class JourneyFoodServiceImpl implements JourneyFoodService {
    private final JourneyFoodOrderRepository repository;

    @Autowired
    private UserService defaultUserService;
    
    public JourneyFoodServiceImpl(JourneyFoodOrderRepository repository) {
        this.repository = repository;
    }   
    @Override
    public List<AggregateJourneyFoodOrder> getOrdersByDateAndNotDisabled(LocalDate mealRetrievalDate) {

    return repository.getOrdersByDateAndNotDisabled("PLACED",mealRetrievalDate);
        //return null;
    }

}

控制器代码 AdminController.java

@Controller
public class AdminController {
    @Autowired
    private JourneyFoodService journeyFoodServiceImpl;
    
    @GetMapping("/fetchTotalQuantityForADate")
public String fetchTotalQuantityForADate(SubmitFetchTotalQuantityModelByDate submitFetchTotalQuantityModelByDate) {
    return "FetchTotalQuantityForADate";
}

@PostMapping("/fetchTotalQuantityForADate")
public String fetchSumOfJourneyFoodOrdersNotDisabled( @Valid @ModelAttribute("submitFetchTotalQuantityModelByDate") SubmitFetchTotalQuantityModelByDate submitFetchTotalQuantityModelByDate
        , BindingResult result, Model model) {
    if (result.hasErrors()) {
        LOGGER.error("AdminController updateOrder method - Error occured");
        return "FetchTotalQuantityForADate";
    }
    LOGGER.info("AdminController fetchSumOfJourneyFoodOrdersNotDisabled method - Enter");
    AggregateJourneyFoodOrder order=journeyFoodServiceImpl.getOrdersByDateAndNotDisabled(submitFetchTotalQuantityModelByDate.getMealRetrievalDate());
     model.addAttribute("order", order==null?null:order);
    LOGGER.info("AdminController fetchSumOfJourneyFoodOrdersNotDisabled method - Exit =>orders: "+order);
    return "fetchAggregateQuantityOrdersByDate";
}
}

我已经尝试过source中提到的解决方案 .请让我知道我在这里做错了什么导致提到的异常。 谢谢

我的查询本身有问题 -

  1. 我已将查询更改为以下查询

  2. 删除了@Modifying注解:这个注解会导致问题,因为更新将return要么是int要么是void,因为我们没有更新任何东西所以这里不需要)

    @Query("SELECT new AggregateJourneyFoodOrder(SUM(headCount), SUM(面包), SUM(achar), SUM(果酱),SUM(其他), SUM(puri), SUM(roti ), SUM(thepla), mealRetrievalDate) FROM JourneyFoodOrder j WHERE j.orderStatus=:orderStatus AND j.mealRetrievalDate = :mealRetrievalDate") AggregateJourneyFoodOrder getOrdersByDateAndNotDisabled(@Param("orderStatus")String orderStatus, @Param("mealRetrievalDate")LocalDate mealRetrievalDate);

    回复