【问题标题】:Need to return List of Custom Object using JPA @Query需要使用 JPA @Query 返回自定义对象列表
【发布时间】:2019-04-06 10:42:18
【问题描述】:

我有一个自定义对象

@Component
public class SaleReport {

    private Date date;
    private String customerName;
    private String phoneNo;
    private String productName;
    private Integer quantity;
    private Double totalAmount;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getPhoneNo() {
        return phoneNo;
    }

    public void setPhoneNo(String phoneNo) {
        this.phoneNo = phoneNo;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Double getTotalAmount() {
        return totalAmount;
    }

    public void setTotalAmount(Double totalAmount) {
        this.totalAmount = totalAmount;
    }
}

我需要使用JpaRepository<Sale, Integer> 返回此对象的列表 SaleRepository 如下:

@Repository
public interface SaleRepository extends JpaRepository<Sale, Integer> {


    @Query(value = "SELECT B.order_date AS date, E.customer_name AS customerName, " +
            "E.phone_no AS phoneNo, D.product_name AS productName, C.quantity AS quantity, " +
            "C.total_price AS totalAmount " +
            "FROM SALE A " +
            "INNER JOIN A.quotation_id B " +
            "INNER JOIN B.quotation_id C " +
            "INNER JOIN C.product_id D " +
            "INNER JOIN B.customer_id E " +
            "WHERE (B.order_date BETWEEN :from_date AND :to_date)", nativeQuery = true)
    public List<SaleReport> getSaleReportByDate(@Param("from_date")String fromDate, @Param("to_date")String toDate);

}

这是我的控制器方法:

@GetMapping("api/report/sale/{from_date}/{to_date}")
        public List<SaleReport> getSaleReportByDate(@PathVariable("from_date") String fromDate, @PathVariable("to_date") String toDate){
        return saleRepository.getSaleReportByDate(fromDate, toDate);
}

当我运行代码时,它显示了这个错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'a'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_161]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_161]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_161]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_161]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.47.jar:5.1.47]
    at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.47.jar:5.1.47]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944) ~[mysql-connector-java-5.1.47.jar:5.1.47]

我的数据库名称没问题。当我在其他方法中请求时,它可以完美运行。 请给我一个理想的解决方案。

【问题讨论】:

  • 此异常是由于应用程序找不到数据库名称。通过手动检查确保您有名为“a”的数据库。
  • 为什么查询正在搜索名为“a”的数据库..?这里是我的数据库信息spring.datasource.url=jdbc:mysql://localhost:3366/andropos_db spring.datasource.username=root spring.datasource.password=1525
  • FROM SALE A " + "INNER JOIN A.quotation_id B " + 看到这个。你正在尝试只对 'a' 数据库做一些事情
  • 我已将SALE A 更改为仅SALE。在这种情况下,查询正在搜索名为“sale”的数据库。现在呢?
  • SaleReport 用“组件”注释。我认为它应该用“实体”注释?

标签: java mysql spring spring-boot jpql


【解决方案1】:

1)您需要为SaleReport 类创建一个构造函数,该构造函数接受您在select 语句中使用的所有参数并按确切顺序。

2) 更改您的查询,以便使用 new 语句包装选定的列:

@Query(value = "SELECT new org.mypackage.SaleReport(B.order_date AS date,"
                        + "E.customer_name AS customerName, "
                        + "E.phone_no AS phoneNo, D.product_name AS productName, 
                        + "C.quantity AS quantity, " +
                        + "C.total_price AS totalAmount) " +
            "FROM SALE A " +
            "INNER JOIN A.quotation B " +
            "INNER JOIN B.quotation C " +
            "INNER JOIN C.product D " +
            "INNER JOIN B.customer E " +
            "WHERE (B.order_date BETWEEN :from_date AND :to_date)") 

3)在我看来,这里不需要原生查询,可以直接使用 HQL(更改连接)。

【讨论】:

  • 显示以下错误:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'saleController': Unsatisfied dependency expressed through field 'saleRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'saleRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List me.chonchol.androposweb.repository.SaleRepository.getSaleReportByDate(java.lang.String,java.lang.String)!
  • 确保使用实体实例变量名而不是直接的数据库列名
【解决方案2】:

Spring 有一个名为 @SqlResultSetMapping 的注解 此注释可用于上述问题。有关此注释的详细信息,请参见以下链接:

Annotation Type ConstructorResult

这实际上是将一个休眠查询结果映射到一个普通的POJO 类。这才是真正需要的。

Example:

   Query q = em.createNativeQuery(
      "SELECT c.id, c.name, COUNT(o) as orderCount, AVG(o.price) AS avgOrder " +
      "FROM Customer c, Orders o " +
      "WHERE o.cid = c.id " +
      "GROUP BY c.id, c.name",
      "CustomerDetailsResult");

   @SqlResultSetMapping(
       name="CustomerDetailsResult",
       classes={
          @ConstructorResult(
               targetClass=com.acme.CustomerDetails.class,
                 columns={
                    @ColumnResult(name="id"),
                    @ColumnResult(name="name"),
                    @ColumnResult(name="orderCount"),
                    @ColumnResult(name="avgOrder", type=Double.class)
                    }
          )
       }
      )

@SqlResultSetMapping 放在任何@Entity 的顶部,并确保从数据库返回的datatype 与您的POJOdatatype 相同。

希望这会对您有所帮助。享受:)

【讨论】:

    【解决方案3】:

    希望这个回答对你有帮助!!

    Sale 是您的实体类,SaleReport 是 pojo 类。

    public List<SaleReport> getSaleReportByDate(@Param("from_date")String fromDate, @Param("to_date")String toDate);
    

    你不能从数据库返回一个 pojo 类列表。它返回实体类列表。 使用公共列表而不是公共列表

    public List<Sale> getSaleReportByDate(@Param("from_date")String fromDate, @Param("to_date")String toDate);
    
    @Repository
    public interface SaleRepository extends JpaRepository<**Sale**, Integer>
    

    您必须将实体类列表映射到 POJO 类列表。

    Entity类列表到pojo类列表的映射: 因为有很多方法可以实现这一点 最简单的解决方案是遍历实体类并将实体属性设置为 pojo 属性:

    我不建议使用构造函数,因为有时您可能只想设置几个字段而不是 POJO 类的所有字段。

    Arraylist<SaleReport> sr = new Arraylist<SaleReport>();
    ArrayList<Sale> saleEntityList= saleRepository.getSaleReportByDate(fromDate,toDate);
    for(Sale  s : saleEntityList){
        saleReport = new SaleReport();
        saleReport.setDate(s.getDate);
        //same for all attributes
        sr.add(saleReport);
    } 
    return sr;
    

    这里 sr 是你的 POJO 列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      • 2016-02-17
      相关资源
      最近更新 更多