【问题标题】:JPQL Create "Dynamic" Query to execute in repositoryJPQL 创建“动态”查询以在存储库中执行
【发布时间】:2016-12-19 09:17:07
【问题描述】:

编辑-

我将添加用例以清除此功能。

用户将选择两个日期 - 开始日期和结束日期 - 然后将它们传递并用于选择表格(每年都有自己的表格)。在两个给定日期位于同一年的一个用例中,仅对该表进行简单查询。

但是,如果这两个日期是不同的年份,我将需要加入所有表(因此 2011-2013 将连接三个表以进行搜索),因此,我需要对此进行动态修复。我知道建立一个像下面这样的查询是违反安全性的——只是认为类似的东西会起作用。由于系统每年都会获得新表,因此我也不想为每个案例手动添加许多新查询(2011-2016、2014-2018、2011-2019 等)


我有一个问题,是否可以像下面这样将动态查询创建为字符串,然后将其传递给服务 -> 存储库,并将其用作查询?

for (int i = 0; i < yearCondition; i++) {
                if (i == 0) {
                    query += "SELECT md.Device_ID, l.locationRef, " + reportRunForm.getStartDate() + " as 'From Date', "
                            + reportRunForm.getEndDate() + " as 'To Date' "
                            + "from mData.meterdata" + iDateStart.substring(0, 4)
                            + " join MOL2.meters m on device_ID = m.meterUI "
                            + "join MOL2.locations l on m.locationID = l.locationID "
                            + "join MOL2.meterreg mr on m.meterID = mr.meterID "
                            + "where mr.userID = ?1";
                }
                query += "UNION SELECT md.Device_ID, l.locationRef, " + reportRunForm.getStartDate() + " as 'From Date', "
                        + reportRunForm.getEndDate() + " as 'To Date' "
                        + "from mData.meterdata" + (Integer.parseInt(iDateStart.substring(0, 4))+i)
                        + " join MOL2.meters m on device_ID = m.meterUI "
                        + "join MOL2.locations l on m.locationID = l.locationID "
                        + "join MOL2.meterreg mr on m.meterID = mr.meterID "
                        + "where mr.userID = ?1";
            }

我可能对它的工作原理有错误的想法,我知道我可以通过 entitymanager 创建和持久化查询,但想知道是否可以通过存储库执行此操作?

我的想法是我会像上面那样构建查询,将其传递给服务,然后传递给存储库,并将其绑定为 @Query 注释中的值,但这似乎不可能。我可能会接近这个错误,所以任何建议都将不胜感激。

谢谢。

编辑 -

搞砸了。完全理解这样做是愚蠢的,我正在寻找一种构建类似东西的方法,它仍然是安全的。

【问题讨论】:

  • 您应该绝不直接向查询添加变量,始终使用准备好的语句和变量替换来防止 sql 注入攻击(有关更多详细信息,请参阅 security.se 上的this post) .
  • 是的,一般来说,我使用准备好的语句,只是在这种情况下我使用了一个变量——但我知道我在哪里弄错了。我无法找到一个可以动态准备这些语句的解决方案,因为要使用的表会发生变化,并且所需的不同查询的数量会太多(想想 2010 年到 2016 年,以及之间的任何年数)数据 - 并且增长了一年)。
  • 你能告诉我动态的价值是什么。
  • 因此,在 UI 上,用户将选择两个日期,一个开始日期和结束日期。开始可能是 2011 年的日期,到 2014 年结束,因为数据库每年都有自己的表,所以我需要在搜索特定日期之间的数据之前将它们联合起来。因此,如果有一次请求,它可能会在一年(所以只有一次迭代)或者更多,它将为下一年添加一个联合,依此类推。它只是用相同的选择扩展查询,只是不同的“来自”(“来自 mData.meterdata”+(Integer.parseInt(iDateStart.substring(0, 4))+i))

标签: java sql spring spring-data-jpa jpql


【解决方案1】:

也许在您的 POJO 之前的这些注释可以提供帮助

@org.hibernate.annotations.Entity(dynamicInsert = true)

【讨论】:

  • 是 OP 使用 Hibernate 吗?
【解决方案2】:

例如两张表区和选区...

动态查询

    query += "select *from constituency c  where 1=1";
if(constituencyNumber!=null) 
    query +=" and c.constituency_number like '"+constituencyNumber+"%'";
query += " group by c.district_id";

                         OR

     select *from constituency c  where (c.constituency_number is null or c.constituency_number like '1%') group by c.district_id;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    相关资源
    最近更新 更多