【问题标题】:Custom Query H2 - Spring Boot自定义查询 H2 - Spring Boot
【发布时间】:2021-07-17 06:32:02
【问题描述】:

我在尝试对 H2 DB 进行自定义查询时尝试执行 Spring Boot Application,但出现错误:

localhost:8080/uniqueInvestmentDetails

{
    "timestamp": 1626502823614,
    "status": 500,
    "error": "Internal Server Error",
    **"exception": "org.springframework.dao.InvalidDataAccessResourceUsageException",
    "message": "could not prepare statement; SQL [SELECT new UniqueInvestments(portal as portal, sum(amount) as amount) from INVESTMENTS group by portal]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement",**
    "path": "/uniqueInvestmentDetails"
}

Investment.java:

package com.spring.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table
public class Investments {

    @Id
    @Column
    public String investment_id;
    @Column
    public String portal;
    @Column
    public String investment_date;
    @Column
    public float amount;
    public String getInvestment_id() {
        return investment_id;
    }
    public void setInvestment_id(String investment_id) {
        this.investment_id = investment_id;
    }
    public String getPortal() {
        return portal;
    }
    public void setPortal(String portal) {
        this.portal = portal;
    }
    public String getInvestment_date() {
        return investment_date;
    }
    public void setInvestment_date(String investment_date) {
        this.investment_date = investment_date;
    }
    public float getAmount() {
        return amount;
    }
    public void setAmount(float amount) {
        this.amount = amount;
    }
    
}

UniqueInvestments.java:

package com.spring.model;

public class UniqueInvestments {

    public String portal;
    public float amount;
    
    public String getPortal() {
        return portal;
    }
    public void setPortal(String portal) {
        this.portal = portal;
    }
    public float getAmount() {
        return amount;
    }
    public void setAmount(float amount) {
        this.amount = amount;
    }
    
    public UniqueInvestments(String portal, float amount) {
        this.portal = portal;
        this.amount = amount;
    }
    
}

存储库:

package com.spring.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.spring.model.Investments;
import com.spring.model.UniqueInvestments;

public interface InvestmentsRepo extends JpaRepository<Investments, Integer> {

    @Query(nativeQuery = true, value = "SELECT "
            + "new UniqueInvestments(portal as portal, sum(amount) as amount) "
            + "from INVESTMENTS group by portal")
    List<UniqueInvestments> getUniqueInvestmentsList();

}

控制器:

package com.spring.Controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.spring.model.Investments;
import com.spring.model.UniqueInvestments;
import com.spring.services.InvestmentsService;

@RestController
public class InvestmentController {

    @Autowired
    InvestmentsService investmentService;
    
    @PostMapping
    public void insertInvestmentDetails(){
        
    }
    
    @GetMapping("/showInvestments")
    public List<Investments> showInvestments(){
        return investmentService.showAllInvestments();
    }
    
    @GetMapping("/uniqueInvestmentDetails")
    public List<UniqueInvestments> showUniqueInvestments(){
        return investmentService.showUniqueInvestments();
    } 
    
}

服务:

package com.spring.services;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.spring.model.Investments;
import com.spring.model.UniqueInvestments;
import com.spring.repository.InvestmentsRepo;

@Service
public class InvestmentsService {

    @Autowired
    InvestmentsRepo investmentRepo;  
    
    public List<Investments> showAllInvestments() {
        List<Investments> investments = new ArrayList<Investments>();  
        investmentRepo.findAll().forEach(investment -> investments.add(investment));  
        return investments;  
    }

    public List<UniqueInvestments> showUniqueInvestments() {
        List<UniqueInvestments> uniqueInvestments = new ArrayList<UniqueInvestments>();  
        for(UniqueInvestments inv : investmentRepo.getUniqueInvestmentsList()){
            uniqueInvestments.add(inv);
        }
        return uniqueInvestments;
    }

}

application.properties:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# Enabling H2 Console
spring.h2.console.enabled=true
 
# Custom H2 Console URL
spring.h2.console.path=/h2

spring.jpa.hibernate.ddl-auto=none

spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

【问题讨论】:

  • 在您的查询中出现SELECT new UniqueInvestments(portal as portal...,new 是错字吗?
  • 你的h2数据库中有数据吗
  • @Dariosicily 好像没有
  • @RohithV 是的,有数据

标签: java spring-boot spring-data-jpa


【解决方案1】:

InvestmentsRepo 类中,删除您的本机查询并将其放入您的实体类中。

@Entity
@Table
@Data
@NamedNativeQuery(
    name = "find_unique_investments",
    query =
            "SELECT "
                    + "i.portal as portal, sum(i.amount) as amount "
                    + "from INVESTMENTS i group by i.portal",
    resultSetMapping = "unique_investments"
)
@SqlResultSetMapping(
    name = "unique_investments",
    classes = @ConstructorResult(
            targetClass = UniqueInvestments.class,
            columns = {
                    @ColumnResult(name = "portal", type = String.class),
                    @ColumnResult(name = "amount", type = Float.class)
            }
    )
)
public class Investments {
........
}

在您的存储库类中,只需调用此namedQuery

@Query(nativeQuery = true, name = "find_unique_investments")
List<UniqueInvestments> getUniqueInvestmentsList();

您当前的问题将得到解决。如果你运行这个 curl:

curl --location --request GET 
'http://localhost:8080/uniqueInvestmentDetails' \
--header 'Content-Type: application/json' \
--data ''

您将得到以下结果(这些来自我在应用程序启动中用于测试目的的虚拟数据):

[
    {
        "portal": "portal1",
        "amount": 600.0
    },
    {
        "portal": "portal2",
        "amount": 250.0
    },
    {
        "portal": "portal3",
        "amount": 350.0
    }
]

【讨论】:

  • 嗨 DevReddit,如果我没有提供新的 UniqueInvestments,则会引发以下错误“异常”:“org.springframework.core.convert.ConversionFailedException”,“消息”:“无法从类型转换 [ java.lang.Object[]] 为值“{Zerodha, 22500.0}”键入 [com.spring.model.UniqueInvestments];嵌套异常是 org.springframework.core.convert.ConverterNotFoundException:找不到能够从类型转换的转换器[java.lang.String] 输入 [com.spring.model.UniqueInvestments]", "path": "/uniqueInvestmentDetails"
  • @Lucifer,编辑了我的帖子,现在可以使用了。
  • 根据您的帖子。我添加了所有细节,现在我得到空结果。没有得到任何结果。对于相同的查询,当我在 H2 DB 中运行得到结果时。
  • @Lucifer,你是保留了spring.jpa.hibernate.ddl-auto=none 还是更改了它?另外,我没听懂你说的,你没有通过应用程序获取数据,而是通过手动运行查询来获取它们?
  • 它有效。我的测试目的不好我更新了'spring.jpa.hibernate.ddl-auto'忘了恢复它。改回原始(即)无后,它起作用了。非常感谢:)
猜你喜欢
  • 2019-07-07
  • 2019-01-12
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 2019-02-16
  • 2020-11-12
相关资源
最近更新 更多