【发布时间】:2020-06-12 16:49:15
【问题描述】:
给定 2 个表,设计状态(通过复合键定义唯一状态)和状态组(定义从设计状态到用户组的外部参照记录),我正在尝试实现一个规范,该规范返回给定用户组的设计状态记录。设计状态与状态组是一对多的关系。下面的代码通过 H2 的单元测试产生正确的结果,但在运行时 SQL Server 中失败,','附近的语法不正确。 我追踪到以下select (costatusgr1_.DESIGN_STAT_CD, costatusgr1_.PRODUCT_ID, costatusgr1_.USER_GROUP_ID)。
如果这个子句是select * from CO_STATUS_GROUP costatusgr1_,SQL Server 将返回正确的结果。我正在寻求帮助修复我的规范以使用 EXISTS 或 IN 对子查询执行选择。
DDL如下:
create table CO_DES_STATUS
(
PRODUCT_ID int not null,
DESIGN_STAT_CD char(2) not null,
DESIGN_STAT_DESC varchar(30),
constraint PK_DES_STATUS
primary key (PRODUCT_ID, DESIGN_STAT_CD)
)
create table CO_STATUS_GROUP
(
PRODUCT_ID int not null,
DESIGN_STAT_CD char(2) not null,
USER_GROUP_ID varchar(8) not null,
constraint PK_STATUS_GROUP
primary key (PRODUCT_ID, DESIGN_STAT_CD, USER_GROUP_ID)
)
等效SQL如下:
select ds.* from CO_DES_STATUS ds
inner join CO_STATUS_GROUP sg on ds.PRODUCT_ID=sg.PRODUCT_ID and ds.DESIGN_STAT_CD=sg.DESIGN_STAT_CD
where ds.PRODUCT_ID=123 and sg.USER_GROUP_ID='group1'
order by ds.DESIGN_STAT_SEQ_NUM
对每个表和复合键使用实体,CoDesStatus 将一对多链接到 productId 和 designStatCd 上的 CoStatusGroup。
Predicate 方法的规范:
public Predicate toPredicate(Root<CoDesStatus> root, CriteriaQuery<?> cq,
CriteriaBuilder criteriaBuilder) {
Subquery<CoStatusGroup> subquery = cq.subquery(CoStatusGroup.class);
Root<CoStatusGroup> subqueryFrom = subquery.from(CoStatusGroup.class);
Join<CoStatusGroup, CoDesStatus> subqueryJoin = subqueryFrom.join(CoStatusGroup_.coDesStatus);
Predicate isAccessingUserPredicate = criteriaBuilder
.equal(subqueryFrom.get(CoStatusGroup_.coSecurityUserGroup), this.accessingUserGroup);
Predicate isProductPredicate = criteriaBuilder.equal(root.get(CoDesStatus_.id).get(CoDesStatusPK_.productId), coProd.getProductId());
Predicate isParentEntityPredicate = criteriaBuilder
.equal(subqueryJoin.get(CoDesStatus_.id), root.get(CoDesStatus_.id));
subquery.select(subqueryFrom).where(isAccessingUserPredicate, isProductPredicate, isParentEntityPredicate);
return criteriaBuilder.exists(subquery);
}
Hibernate 查询结果:
Hibernate: select codesstatu0_.DESIGN_STAT_CD as DESIGN_S1_70_, codesstatu0_.PRODUCT_ID as PRODUCT_2_70_, codesstatu0_.DESIGN_STAT_DESC as DESIGN_S5_70_ from CO_DES_STATUS codesstatu0_ where exists (select (costatusgr1_.DESIGN_STAT_CD, costatusgr1_.PRODUCT_ID, costatusgr1_.USER_GROUP_ID) from CO_STATUS_GROUP costatusgr1_ inner join CO_DES_STATUS codesstatu2_ on costatusgr1_.DESIGN_STAT_CD=codesstatu2_.DESIGN_STAT_CD and costatusgr1_.PRODUCT_ID=codesstatu2_.PRODUCT_ID where costatusgr1_.USER_GROUP_ID='group1' and codesstatu0_.PRODUCT_ID=123 and codesstatu2_.DESIGN_STAT_CD=codesstatu0_.DESIGN_STAT_CD and codesstatu2_.PRODUCT_ID=codesstatu0_.PRODUCT_ID)
错误:
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 102, SQLState: S0001
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Incorrect syntax near ','.
【问题讨论】:
-
您好,您是否尝试使用查询分析器或其他 SQL Server 工具验证生成的查询的语法?
-
是的,使用 SQL Server 控制台我得到了与描述相同的错误。但是,一旦我将查询更改为
where exists(select * from CO_STATUS_GROUP costatusgr1_,它就会按预期工作。错误告诉我此部分中的逗号无效:where exists(select **(costatusgr1_.DESIGN_STAT_CD, costatusgr1_.PRODUCT_ID, costatusgr1_.USER_GROUP_ID)** from CO_STATUS_GROUP costatusgr1_.
标签: java sql-server hibernate jpa subquery