SQL Server 数据库中带有 Group by 子句的 JPQL 不起作用
Posted
技术标签:
【中文标题】SQL Server 数据库中带有 Group by 子句的 JPQL 不起作用【英文标题】:JPQL with Group by clause in SQL Server database not working 【发布时间】:2021-12-16 12:34:36 【问题描述】:我是 SQL Server 数据库的新手。下面的 JPQL 查询没有被执行,也没有抛出任何错误。只是我的应用程序挂在这个查询上。此代码适用于 mysql 数据库,但不适用于 SQL Server(2019) 数据库。
@Query(value = "SELECT R.riskType, count(distinct V.bname) FROM RiskViolation V JOIN V.job J JOIN V.risk R WHERE J.id = ?1 GROUP BY R.riskType ")
public List<Object[]> sodUserByRiskType(Long jobId);
但是当我直接在 SQL Server 数据库中运行以下转换后的 sql 查询时,它工作正常。
select count(distinct riskviolat0_.bname) as col_1_0_, risklog2_.risk_type as col_0_0_ from risk_violation riskviolat0_ inner join analysis_job analysisjo1_ on riskviolat0_.job_id=analysisjo1_.id inner join risk_log risklog2_ on riskviolat0_.risk_id=risklog2_.id where analysisjo1_.id=? group by risklog2_.risk_type;
以下是 JPQL 查询中使用的 Java 实体类:
RiskViolation.java
@Entity
@Table(name = "risk_violation")
public class RiskViolation
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "job_id")
private AnalysisJob job;
private String bname;
private String riskName;
private String violations;
@Column(name = "violated", columnDefinition = "BIT", length = 1)
private boolean violated;
@Column(name = "simulation", columnDefinition = "BIT", length = 1)
private boolean simulation;
@Column(name = "mitigation_name")
private String mitigationName;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "risk_id")
private RiskLog risk;
@JsonIgnore
@OneToMany(mappedBy = "riskViolation", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<RuleViolation> ruleViolations;
AnalysisJob.java
@Entity
@Table(name = "analysis_job")
public class AnalysisJob
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "profile_name")
private String profileName;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "profile_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private AnalysisProfileLog profileLog;
@Column(name = "description")
private String description;
@Column(name = "status")
private String status;
@Column(name = "started_on")
private Date startedOn;
@Column(name = "completed_on")
private Date completedOn;
@Column(name = "completion_message")
private String completionMessage;
@Column(name = "percent_completed")
private float percentCompleted;
@Column(name = "run_by")
private String runBy;
@Column(name = "removed", columnDefinition = "BIT", length = 1)
private boolean removed;
@OneToMany(mappedBy = "job", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
private List<JobResultData> resultData;
@Column(name = "pos_analysis", columnDefinition = "BIT", length = 1)
private boolean posAnalysis;
@Column(name = "submitted", columnDefinition = "BIT", length = 1)
private boolean submitted;
@Column(name = "position_id")
private String positionId;
RiskLog.java
@Entity
@Table(name = "risk_log")
public class RiskLog
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long jobId;
private String name;
private String riskDescription;
private String riskCondition;
private String businessProcess;
@Column(name = "business_sub_process")
private String subProc;
private String riskType;
@JsonIgnore
@OneToMany(mappedBy = "riskLog", cascade = CascadeType.ALL)
protected List<RuleLog> rules;
是否需要对查询和实体类进行任何更改才能使其正常工作?
这里是Query Plan URL
Estimated Execution Plan
Actual Execution Plan
Query Plan with Actual Rows
【问题讨论】:
请通过brentozar.com/pastetheplan分享查询计划。要获得正在运行的查询计划,请在 Jpql 执行查询select qp.query_plan from sys.dm_exec_requests r cross apply sys.dm_exec_query_plan(r.plan_handle) qp where r.session_id <> @@SPID
时在 SSMS 中运行它
感谢@Charlieface 的回复。我已经用底部的查询计划 url 更新了我的问题。
尝试索引risk_violation (job_id, bname)
,您无能为力。您可以从 SSMS 上传“实际”执行计划吗?最终结果集有多少行,从预估的计划中看不到?
按照您的建议添加了索引,但仍然相同。我不确定我是否正确运行查询计划。这次我在工具栏上选择了“包括实际执行计划”和“包括实时查询统计”选项并执行。请查看带有新查询计划的更新问题。
现在,我知道了如何获得实际的查询计划。给我几分钟,我会补充的。
【参考方案1】:
它在避免 Java 类(我的业务逻辑所在的位置)和 JPA 存储库(用于执行 JPQL 查询)之间的外观类之后起作用。从 Java 类直接调用 JPA 存储库方法。不知道为什么它不适用于带有 SQL Server 的外观类,但同样适用于 MySQL 数据库。
【讨论】:
以上是关于SQL Server 数据库中带有 Group by 子句的 JPQL 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
列子句中带有子查询的 MS SQL Server 数据透视表
SQL Server 中带有 while 循环的用户定义函数