Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过查询从Spring数据JPA组返回自定义对象_Java_Spring_Spring Mvc_Jpa_Repository - Fatal编程技术网

Java 如何通过查询从Spring数据JPA组返回自定义对象

Java 如何通过查询从Spring数据JPA组返回自定义对象,java,spring,spring-mvc,jpa,repository,Java,Spring,Spring Mvc,Jpa,Repository,我正在用SpringDataJPA开发一个SpringBoot应用程序。我正在使用一个定制的JPQL查询来按某个字段分组并获取计数。以下是我的存储库方法 @Query(value = "select count(v) as cnt, v.answer from Survey v group by v.answer") public List<?> findSurveyCount(); 我想得到这样的东西: [ { "cnt":1, "answer":"a1" }, { "c

我正在用SpringDataJPA开发一个SpringBoot应用程序。我正在使用一个定制的JPQL查询来按某个字段分组并获取计数。以下是我的存储库方法

@Query(value = "select count(v) as cnt, v.answer from Survey v group by v.answer")
public List<?> findSurveyCount();
我想得到这样的东西:

[
  { "cnt":1, "answer":"a1" },
  { "cnt":2, "answer":"a2" }
]

如何实现这一点?

此SQL查询返回列表

您可以这样做:

@RestController
@请求映射(“/survey”)
公共类测量控制器{
@自动连线
私人调查报告调查报告;
@RequestMapping(value=“/find”,method=RequestMethod.GET)
公共地图搜索(){
列表结果=surveyRepository.findSurveyCount();
Map=null;
if(result!=null&&!result.isEmpty()){
map=新的HashMap();
对于(对象[]对象:结果){
map.put(((长)对象[0]),对象[1]);
}
}
返回图;
}
}
JPQL查询解决方案 中的JPQL查询支持这一点

步骤1:声明一个简单的bean类

步骤2:从存储库方法返回bean实例

步骤2:从查询中返回预计属性

public interface survey repository扩展了crudepository{
@查询(nativeQuery=true,值=
“选择”+
“v.答案作为答案,将(v)计数为cnt”+
“来自”+
“调查五”+
“分组依据”+
“五、答复”)
列出findSurveyCount();
}

使用SQL
AS
关键字将结果字段映射到投影属性,以实现明确的映射。

定义一个自定义pojo类,并将查询返回值存储在自定义pojo类中

@Query(value = "select new com.xxx.xxx.class.SureveyQueryAnalytics(s.answer, count(sv)) from Survey s group by s.answer")
List<SureveyQueryAnalytics> calculateSurveyCount();
@Query(value=“通过s.answer从调查s组中选择新的com.xxx.xxx.class.SureveyQueryAnalytics(s.answer,count(sv)))
列表calculateSurveyCount();

我知道这是一个老问题,它已经得到了回答,但这里有另一种方法:

@Query("select new map(count(v) as cnt, v.answer) from Survey v group by v.answer")
public List<?> findSurveyCount();
@Query(“按v.answer从调查v组中选择新地图(将(v)计数为cnt,v.answer))
公共列表findSurveyCount();

我不喜欢查询字符串中的java类型名称,而是使用特定的构造函数来处理它。 Spring JPA使用HashMap参数中的查询结果隐式调用构造函数:

@Getter
public class SurveyAnswerStatistics {
  public static final String PROP_ANSWER = "answer";
  public static final String PROP_CNT = "cnt";

  private String answer;
  private Long   cnt;

  public SurveyAnswerStatistics(HashMap<String, Object> values) {
    this.answer = (String) values.get(PROP_ANSWER);
    this.count  = (Long) values.get(PROP_CNT);
  }
}

@Query("SELECT v.answer as "+PROP_ANSWER+", count(v) as "+PROP_CNT+" FROM  Survey v GROUP BY v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
@Getter
公共类调查和统计{
公共静态最终字符串PROP_ANSWER=“ANSWER”;
公共静态最终字符串PROP_CNT=“CNT”;
私有字符串应答;
私人长cnt;
公共调查和统计(HashMap值){
this.answer=(字符串)values.get(PROP_answer);
this.count=(长)values.get(PROP_CNT);
}
}
@查询(“选择v.answer作为“+PROP_answer+”,按v.answer从调查v组中将(v)计数为“+PROP_CNT+”)
列出findSurveyCount();

代码需要Lombok来解析@Getter

,使用接口可以得到更简单的代码。无需创建和手动调用构造函数

步骤1:使用必填字段声明接口:

公共接口调查和统计{
字符串getAnswer();
长getCnt();
}
步骤2:在界面中选择与getter同名的列,并从存储库返回intefrace方法:

public interface survey repository扩展了crudepository{
@查询(“选择v.answer作为答案,将(v)计数为cnt”+
“来自调查v”+
“按v.答案分组”)
列出findSurveyCount();
}

我刚刚解决了这个问题:

  • 基于类的投影不适用于查询本机(
    @query(value=“SELECT…”,nativeQuery=true
    ),因此我建议使用接口定义自定义DTO
  • 在使用DTO之前,应该验证查询语法是否正确
我使用自定义DTO(接口)将本机查询映射到-最灵活的方法和最安全的重构

我遇到的问题是——令人惊讶的是,接口中字段的顺序和查询中的列很重要。我通过按字母顺序排列接口getter,然后以相同的方式对查询中的列进行排序,从而使其正常工作。

@Repository
@Repository
public interface ExpenseRepo extends JpaRepository<Expense,Long> {
    List<Expense> findByCategoryId(Long categoryId);

    @Query(value = "select category.name,SUM(expense.amount) from expense JOIN category ON expense.category_id=category.id GROUP BY expense.category_id",nativeQuery = true)
    List<?> getAmountByCategory();

}
公共接口费用Repo扩展了JpaRepository{ 列表findByCategoryId(长类别); @查询(value=“从费用上的费用加入类别中选择类别.名称,金额(费用.金额)。类别\u id=类别.id按费用分组。类别\u id”,nativeQuery=true) 列出getAmountByCategory(); }

上面的代码对我有用

使用JDBC获取具有列名及其值(在键值对中)的数据:

/*Template class with a basic set of JDBC operations, allowing the use
  of named parameters rather than traditional '?' placeholders.
 
  This class delegates to a wrapped {@link #getJdbcOperations() JdbcTemplate}
  once the substitution from named parameters to JDBC style '?' placeholders is
  done at execution time. It also allows for expanding a {@link java.util.List}
  of values to the appropriate number of placeholders.
 
  The underlying {@link org.springframework.jdbc.core.JdbcTemplate} is
  exposed to allow for convenient access to the traditional
  {@link org.springframework.jdbc.core.JdbcTemplate} methods.*/


@Autowired
protected  NamedParameterJdbcTemplate jdbc;


@GetMapping("/showDataUsingQuery/{Query}")
    public List<Map<String,Object>> ShowColumNameAndValue(@PathVariable("Query")String Query) throws SQLException {

      /* MapSqlParameterSource class is intended for passing in a simple Map of parameter values
        to the methods of the {@link NamedParameterJdbcTemplate} class*/

       MapSqlParameterSource msp = new MapSqlParameterSource();

       // this query used for show column name and columnvalues....
        List<Map<String,Object>> css = jdbc.queryForList(Query,msp);

        return css;
    }

/*模板类,包含一组基本的JDBC操作,允许使用
使用命名参数而不是传统的“?”占位符。
此类委托给包装的{@link#getjdbc操作()jdbc模板}
一旦完成从命名参数到JDBC样式“?”占位符的替换
在执行时完成。它还允许扩展{@link java.util.List}
将值添加到适当数量的占位符。
底层{@link org.springframework.jdbc.core.JdbcTemplate}是
暴露在外,以便方便地访问传统的
{@link org.springframework.jdbc.core.JdbcTemplate}方法*/
@自动连线
受保护名称参数jdbc模板jdbc;
@GetMapping(“/showDataUsingQuery/{Query}”)
公共列表ShowColumnNameAndValue(@PathVariable(“查询”)字符串查询)引发SQLException{
/*MapSqlParameterSource类用于传递参数值的简单映射
到{@link NamedParameterJdbcTemplate}类的方法*/
MapSqlParameterSource msp=新的MapSqlParameterSource();
//此查询用于显示列名和列值。。。。
List css=jdbc.queryForList(Query,msp);
返回css;
}
//正在使用中
`
公共列表findDevicesPerCustomer(){
public interface SurveyRepository extends CrudRepository<Survey, Long> {
    @Query(nativeQuery = true, value =
           "SELECT " +
           "    v.answer AS answer, COUNT(v) AS cnt " +
           "FROM " +
           "    Survey v " +
           "GROUP BY " +
           "    v.answer")
    List<SurveyAnswerStatistics> findSurveyCount();
}
@Query(value = "select new com.xxx.xxx.class.SureveyQueryAnalytics(s.answer, count(sv)) from Survey s group by s.answer")
List<SureveyQueryAnalytics> calculateSurveyCount();
@Query("select new map(count(v) as cnt, v.answer) from Survey v group by v.answer")
public List<?> findSurveyCount();
@Getter
public class SurveyAnswerStatistics {
  public static final String PROP_ANSWER = "answer";
  public static final String PROP_CNT = "cnt";

  private String answer;
  private Long   cnt;

  public SurveyAnswerStatistics(HashMap<String, Object> values) {
    this.answer = (String) values.get(PROP_ANSWER);
    this.count  = (Long) values.get(PROP_CNT);
  }
}

@Query("SELECT v.answer as "+PROP_ANSWER+", count(v) as "+PROP_CNT+" FROM  Survey v GROUP BY v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
@Repository
public interface ExpenseRepo extends JpaRepository<Expense,Long> {
    List<Expense> findByCategoryId(Long categoryId);

    @Query(value = "select category.name,SUM(expense.amount) from expense JOIN category ON expense.category_id=category.id GROUP BY expense.category_id",nativeQuery = true)
    List<?> getAmountByCategory();

}
/*Template class with a basic set of JDBC operations, allowing the use
  of named parameters rather than traditional '?' placeholders.
 
  This class delegates to a wrapped {@link #getJdbcOperations() JdbcTemplate}
  once the substitution from named parameters to JDBC style '?' placeholders is
  done at execution time. It also allows for expanding a {@link java.util.List}
  of values to the appropriate number of placeholders.
 
  The underlying {@link org.springframework.jdbc.core.JdbcTemplate} is
  exposed to allow for convenient access to the traditional
  {@link org.springframework.jdbc.core.JdbcTemplate} methods.*/


@Autowired
protected  NamedParameterJdbcTemplate jdbc;


@GetMapping("/showDataUsingQuery/{Query}")
    public List<Map<String,Object>> ShowColumNameAndValue(@PathVariable("Query")String Query) throws SQLException {

      /* MapSqlParameterSource class is intended for passing in a simple Map of parameter values
        to the methods of the {@link NamedParameterJdbcTemplate} class*/

       MapSqlParameterSource msp = new MapSqlParameterSource();

       // this query used for show column name and columnvalues....
        List<Map<String,Object>> css = jdbc.queryForList(Query,msp);

        return css;
    }

    //in Service      
      `
                public List<DevicesPerCustomer> findDevicesPerCustomer() {
                    LOGGER.info(TAG_NAME + " :: inside findDevicesPerCustomer : ");
                    List<Object[]> list = iDeviceRegistrationRepo.findDevicesPerCustomer();
                    List<DevicesPerCustomer> out = new ArrayList<>();
                    if (list != null && !list.isEmpty()) {
                        DevicesPerCustomer mDevicesPerCustomer = null;
                        for (Object[] object : list) {
                            mDevicesPerCustomer = new DevicesPerCustomer();
mDevicesPerCustomer.setCustomerId(object[0].toString());
                            mDevicesPerCustomer.setCount(Integer.parseInt(object[1].toString()));
                            
                            out.add(mDevicesPerCustomer);
                        }
                    }
            
                    return out;
                }`
        
    //In Repo
        `   @Query(value = "SELECT d.customerId,count(*) FROM senseer.DEVICE_REGISTRATION d  where d.customerId is not null group by d.customerId", nativeQuery=true)
            List<Object[]> findDevicesPerCustomer();`