Spring Data JPA - 将列名和值作为参数传递

Posted

技术标签:

【中文标题】Spring Data JPA - 将列名和值作为参数传递【英文标题】:Spring Data JPA - Pass column name and value as parameters 【发布时间】:2018-05-04 13:25:27 【问题描述】:

我只是想知道如何将列名及其值传递给 Spring Data JPA 中的 @Query 注释。

基本上列名将是静态的,我们曾经将每一列作为一个元素放在 Entity 类中。但是在这里我想要一些不同的东西,这里的列名是动态的,我将把这个值作为参数传递给存储库中定义的方法。

表格 - 日历

- id、PersonName、1、2、3......31

上面是表结构,1,2,3,.....31 是代表日历日的列名,我们在这些列中有值。我正在使用 Spring Data JPA 从数据库中获取数据。 在这里,我只想获取特定日期的人名。 下面给出存储库中定义的函数。

@Query("select c from Calendar c where :calendarDay=:value")
List<Calendar> getPersonName(@Param("calendarDay") String calendarDay, @Param("value") String value);

这对我不起作用。 任何帮助将不胜感激。

【问题讨论】:

也许 spring JPA Spel 会有所帮助,spring.io/blog/2014/07/15/… 你需要使用Criteria API 使用spring数据QueryDsl怎么样?你想过吗? 确实,尝试使用 SPeL:docs.spring.io/spring-data/jpa/docs/current/reference/html/… 我在这里发布了所有我知道的 spring-data 方式(也包括你的问题),***.com/questions/48520827/… 【参考方案1】:

看看sping data Specifications。您可以在那里找到您的解决方案! 阅读文档,您可以看到如果 Calendar 是您的域(我会尝试为我的域找到一个不同的名称,Java SE 中已经有一个 Calendar 类),那么您可以使用类似上面的内容,

@Repository
public interface CalendarRepository extends JpaRepository<Calendar, Integer>, JpaSpecificationExecutor<Calendar> 



public class CalendarSpecification implements Specification<Calendar> 

    private String randomColumnName; // A varchar column.
    private String valueToSearchFor;

    public CalendarSpecification(String randomColumnName, String valueToSearchFor) 
        this.randomColumnName = randomColumnName;
        this.valueToSearchFor = valueToSearchFor;
    

    @Override
    public Predicate toPredicate(Root<Calendar> root, CriteriaQuery<?> query, CriteriaBuilder builder) 
        return builder.and(builder.equal(root.<String>get(this.randomColumnName), this.valueToSearchFor));
    



@Service
public class CalendarService 

    @Autowired
    private CalendarRepository calendarRepository;

    public List<Calendar> findCustom(String randomColumnName, String valueToSearchFor) 
        CalendarSpecification cs = new CalendarSpecification(randomColumnName, valueToSearchFor);
        return calendarRepository.find(cs);
        // Or using lambda expression - without the need of CalendarSpecification class.
//      return calendarRepository.find((Root<ProductCategory> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> 
//          return builder.and(builder.equal(root.<String>get(randomColumnName), valueToSearchFor));
//      );
    

【讨论】:

【参考方案2】:

Spring JPA 支持的唯一动态参数是##entityName。不支持 @Query 注释中的动态列名。这就是您要完成的任务。

您唯一的选择是使用 QueryDSL、Specifications 或 Criteria API 手动构建查询,或者只是构建一个查询字符串并将其传递给您的 EntityManager。无论如何,您都必须为此编写代码。

参见,例如:

https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/ How to add custom column name Spring Data JPA?

【讨论】:

【参考方案3】:

也许你可以使用CASEWHEN

SELECT 
   Id,
   PersonName,
CASE
    WHEN ? = 'day_01' THEN day_01
    WHEN ? = 'day_02' THEN day_02
    WHEN ? = 'day_03' THEN day_03
    WHEN ? = 'day_04' THEN day_04
    WHEN ? = 'day_05' THEN day_05'
    ELSE 0
END
 AS Value FROM Calendar

Java 代码

// customize entity
public interface ITask 
    Long getId();
    String getName();
    String getValue();


@Repository
public interface CalendarRepository 
    static final String CASE_WHEN = "\nCASE\n"
            + "    WHEN :field = 'day_01' THEN day_01\n"
            + "    WHEN :field = 'day_02' THEN day_02\n"
            + "    WHEN :field = 'day_03' THEN day_03\n"
            + "    WHEN :field = 'day_04' THEN day_04\n"
            + "    WHEN :field = 'day_05' THEN day_05\n"
            + "    ELSE 0\n"
            + "END\n";
    
    @Query(nativeQuery = true, value = "SELECT Id, PersoneName, " + CASE_WHEN + " AS Value FROM Calendar WHERE field = :field")
    public List<ITask> findValues(@Param(value = "field") String field);

【讨论】:

【参考方案4】:

你可以像这样使用nativeQuery=true..

@Query(value = "select c from Calendar c where c.:calendarDay=:value", nativeQuery = true)
List<Calendar> getPersonName(@Param("calendarDay") String calendarDay, @Param("value") String value);

【讨论】:

这似乎不起作用

以上是关于Spring Data JPA - 将列名和值作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 原生查询结果实体

处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型

Spring Data JPA Custom Repository

Spring Data JPA - 规范和 Querydsl

spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param

Spring Data JPA @Modifying 注解使用@Transactional