【问题标题】:How to replace table name with parameter value while using Spring Data JPA nativeQuery使用 Spring Data JPA nativeQuery 时如何用参数值替换表名
【发布时间】:2017-04-18 18:27:54
【问题描述】:

像这样:

public interface XXXRepository extends CrudRepository<XXX, Integer> {
@Query(value = "select * from ?1 where ...", nativeQuery = true)
List<XXX> findByXXX(String tableName, ...);}

它在代码中给出了 MYSQL 语法错误。 语法错误表明SQL中的表名被“'”包围。

【问题讨论】:

  • 请发布您的异常堆栈。

标签: java spring spring-data-jpa nativequery


【解决方案1】:

这是不可能的。参数只能在 where 子句中使用。

【讨论】:

    【解决方案2】:

    如果您使用的是 Spring Data 存储库,则可以使用 #{#entityName} SpEL 表达式作为实体名称的占位符。根据您的用例,不再需要使用实体名称作为方法参数。

    我不确定这个功能在你使用nativeQuery = true时是否有效

    在此处查看文档:https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/#jpa.query.spel-expressions

    【讨论】:

    • 它不适用于本机查询,仅适用于 HQL。
    【解决方案3】:

    您可以在 JPA 项目中使用EntityManager

       @Autowired
       EntityManager entityManager;
    
       Query createQuery(String tableName) {
           return entityManager.createNativeQuery("select * from " + tableName);
       }
    

    【讨论】:

      【解决方案4】:

      我有一个解决方法。
      它使用 javax.persistence.EntityManager 和 String.format 来做到这一点。

      package com.example.test.dao;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      
      import java.util.List;
      import javax.persistence.EntityManager;
      
      @Component
      public class SomeDao {
          @Autowired
          EntityManager em;
      
          public List<?> listFoodMoneyDateOfPayment(int departmentId, String sumKey, String tableName) {
              String s = "SELECT SUM(%s) AS money, CONCAT(YEAR(apply_time), '-', MONTH(apply_time)) AS yearmonth " +
                      "FROM (%s) WHERE department_id = %d GROUP BY yearmonth";
              String sql = String.format(s, sumKey, tableName, departmentId);
              System.out.println(sql);
      
              List<?> test = em.createNativeQuery(sql).getResultList();
      
              return test;
          }
      }
      
      

      调用代码是:

      @RestController
      @RequestMapping("/api")
      public class TestController {
      
          @Autowired
          private SomeDao dao;
      
          @RequestMapping("/test2")
          public HttpEntity test2() {
              var l = dao.listFoodMoneyDateOfPayment(12, "food_payment", "payment_application");
              System.out.println(l.getClass());
              System.out.println(JSON.toJSONString(l));
              return ResultBean.success();
          }
      }
      
      

      而且效果很好。
      但是你应该检查传入的参数。

      【讨论】:

        【解决方案5】:

        这可以通过 jdbc 实现:

        @Autowired
        JdbcTemplate jdbcTemplate;
        
        public String nativeQueryToString(String query) {
        
            try {
        
                return jdbcTemplate.queryForObject(query, String.class);
                
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-27
          • 2018-05-20
          • 1970-01-01
          • 2014-05-22
          • 2017-11-23
          • 2019-07-26
          • 2020-04-05
          • 2022-01-21
          相关资源
          最近更新 更多