[英]Is there a way to use column name as a parameter in a query using Spring Data JPA?
我正在编写一个用于 NBA 统计数据可视化的应用程序。 我正在使用 Spring Boot + MySql 数据库。 我试图从每列中找到最小值和最大值,条件是玩家必须至少玩 10 场比赛。 为此,我可以编写如下方法:
@Repository
public interface PerGameStatsRepository extends JpaRepository<PerGameStats, PerGameStatsId> {
@Query(value = "SELECT MAX(stats.pts) FROM PerGameStats stats WHERE stats.gamesPlayed >= 10")
BigDecimal findMaxAmountOfPoints();
@Query(value = "SELECT MIN(stats.pts) FROM PerGameStats stats WHERE stats.gamesPlayed >= 10")
BigDecimal findMinAmountOfPoints();
}
然而,该表有大约 15 列,如得分、篮板、助攻、盖帽等(我可能会添加更多)。 为了获得它们中的每一个的最小值和最大值,我必须为每列编写 2 个方法:2x15 = 30 总数。 有没有办法避免这种重复并编写一个将列名作为参数并基于它执行正确查询的方法? 就像是:
// this obviously doesn't work
@Query(value = "SELECT MAX(stats.:#{#fieldName}) FROM PerGameStats stats WHERE stats.gamesPlayed >= 10")
BigDecimal findMaxAmountOfField(String fieldName);
对于这种情况,您必须创建一个自定义存储库实现。 这样的事情应该工作:
interface CustomizedPerGameStatsRepository {
BigDecimal findMaxAmountOfField(String fieldName);
}
使用以下实现:
class CustomizedPerGameStatsRepositoryImpl implements CustomizedPerGameStatsRepository { // name has to be ...Impl
private final EntityManager em;
@Autowired
public CustomizedPerGameStatsRepositoryImpl(JpaContext context) {
this.em = context.getEntityManagerByManagedType(PerGameStats.class);
}
public BigDecimal findMaxAmountOfField(String fieldName) {
return (BigDecimal) em.createQuery("SELECT MAX(" + fieldName + ") FROM PerGameStats stats WHERE stats.gamesPlayed >= 10")
.getSingleResult();
}
}
以及您存储库中的更改:
@Repository
public interface PerGameStatsRepository extends JpaRepository<PerGameStats, PerGameStatsId>, CustomizedPerGameStatsRepository {
}
您可以使用投影:
interface MinMaxProjection {
BigDecimal getMin();
BigDecimal getMax();
}
那么你的存储库应该如下所示:
@Query(value = "SELECT MIN(stats.pts) as min, MAX(stats.pts) as max FROM PerGameStats stats WHERE stats.gamesPlayed >= 10")
MinMaxProjection findMinMaxAmountOfPoints();
}
那么你的回答应该是:
{
max: 460,
min: 200,
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.