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

6

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

基本上,列名将是动态的,我们将通过将此值作为参数传递给存储库中定义的方法来实现。表名为Calendar,列名为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);

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


1
也许Spring JPA Spel会有所帮助,https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions - Aliaksei Stadnik
你需要使用 Criteria API。 - Robert Niestroj
你考虑过使用Spring Data QueryDsl吗? - pvpkiran
确实,尝试使用SPeL:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query.spel-expressions - Ilya Novoseltsev
我在这里发布了我所知道的所有spring-data的方法(包括你的问题),链接如下:https://dev59.com/fqjka4cB1Zd3GeqPB6I2#48541323 - Georgios Syngouroglou
3个回答

7
Spring JPA支持的唯一动态参数是#{#entityName}。在@Query注释中使用动态列名是不被支持的,而这正是你希望实现的内容。
你唯一的选择是手动构建查询,可以使用QueryDSL、Specifications或Criteria API,或者简单地构建一个查询字符串并将其传递给你的EntityManager。无论哪种方式,你都需要编写代码来实现。
例如,请参见:

4
请看 Spring Data规范,您可以在那里找到解决方案!
阅读文档后,您会发现如果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
也许你可以使用 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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接