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】:也许你可以使用CASE
、WHEN
。
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 - 将列名和值作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章
处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型
Spring Data JPA Custom Repository
Spring Data JPA - 规范和 Querydsl