ManyToMany 属性的 SELECT 上的 JPQL Hibernate SQLException

Posted

技术标签:

【中文标题】ManyToMany 属性的 SELECT 上的 JPQL Hibernate SQLException【英文标题】:JPQL Hibernate SQLException on SELECT of ManyToMany attribute 【发布时间】:2012-05-22 07:21:47 【问题描述】:

我正在使用 JPA 和 Hibernate 处理 Java Spring 项目。有两个实体“主题”和“导师”。在“主题”类中,有一个多对多列表作为对“导师”的引用,您可以在下面的 sn-p 中看到:

public class Topic implements Serializable 
   ...    
   @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
   @JoinColumn(name = "pretutor_id")
   @IndexColumn(name = "id")
   private List<Tutor> preferedTutors = new ArrayList<Tutor>();
   ....

“Tutor”实体没有向后引用“Topic”。

我想要实现的是获得一个包含所有主题的主题列表,这些主题在它们的preferedTutors List 属性中包含某个Tutor 对象。为此,我尝试了

"SELECT t FROM Topic t WHERE :tutor MEMBER OF t.preferedTutors"

其中参数“:tutor”是一个“Tutor”对象。 代码编译正确,但在测试中执行时不幸收到以下错误:

Caused by: java.sql.SQLException: Unexpected token: . in statement [select topic0_.id as id4_0_, diplomate2_.id as id1_1_, tutor4_.id as id1_2_, topicdescr5_.id as id6_3_, topic0_.descriptionfile_id as descript3_4_0_, topic0_.procedure_id as procedure4_4_0_, topic0_.diplomate_id as diplomate5_4_0_, topic0_.title as title4_0_, topic0_.tutor_id as tutor6_4_0_, diplomate2_.accountName as accountN2_1_1_, diplomate2_.description as descript3_1_1_, diplomate2_.procedure_id as procedure8_1_1_, diplomate2_.email as email1_1_, diplomate2_.firstname as firstname1_1_, diplomate2_.lastname as lastname1_1_, diplomate2_.title as title1_1_, prospectiv1_.Topic_id as Topic1_4_0__, prospectiv1_.prospectiveDiplomates_id as prospect2_0__, prospectiv1_.id as id0__, tutor4_.accountName as accountN2_1_2_, tutor4_.description as descript3_1_2_, tutor4_.procedure_id as procedure8_1_2_, tutor4_.email as email1_2_, tutor4_.firstname as firstname1_2_, tutor4_.lastname as lastname1_2_, tutor4_.title as title1_2_, tutor4_.contingent as contingent5_2_, tutor4_.createdAt as createdAt5_2_, tutor4_.isAdmin as isAdmin5_2_, preferedtu3_.Topic_id as Topic1_4_1__, preferedtu3_.preferedTutors_id as prefered2_1__, preferedtu3_.id as id1__, topicdescr5_.file as file6_3_, topicdescr5_.fileName as fileName6_3_, topicdescr5_.fileType as fileType6_3_, topicdescr5_.uploadDate as uploadDate6_3_ from Topic topic0_ left outer join Topic_Diplomate prospectiv1_ on topic0_.id=prospectiv1_.Topic_id left outer join Diplomate diplomate2_ on prospectiv1_.prospectiveDiplomates_id=diplomate2_.id left outer join Topic_Tutor preferedtu3_ on topic0_.id=preferedtu3_.Topic_id left outer join Tutor tutor4_ on preferedtu3_.preferedTutors_id=tutor4_.id left outer join TopicDescription topicdescr5_ on topic0_.descriptionfile_id=topicdescr5_.id cross join Topic_Tutor preferedtu6_, Tutor tutor7_ where topic0_.id=preferedtu6_.Topic_id and preferedtu6_.preferedTutors_id=tutor7_.id and (topic0_.diplomate_id is not null) and (. is not null)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:248)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:302)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:452)
at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1616)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2449)
... 58 more

显然是“。”无法处理生成语句末尾的表达式“(. is not null)”。这是一个已知的错误还是我必须更改我的 JPA 查询?

谢谢,马克斯

【问题讨论】:

【参考方案1】:

尝试使用 @JoinTable 定义您的 ManyToMany,如下所示:

public class Topic implements Serializable 
   ...    
   @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
   @JoinTable(name="preferredtutors", joinColumns=@JoinColumn(name="topic_id"), inverseJoinColumns=@JoinColumn(name="tutor_id"))
   private List<Tutor> preferedTutors = new ArrayList<Tutor>();
   ....

您可以使用@JoinTable 注释定义表和列引用。

【讨论】:

以上是关于ManyToMany 属性的 SELECT 上的 JPQL Hibernate SQLException的主要内容,如果未能解决你的问题,请参考以下文章

教义,编辑 ManyToMany - 重载属性的间接修改

django - manytomany 上的查询过滤器为空

Django:模型设计,ManyToMany 属性字段?

Django ManyToMany 字段上的自定义列名

单个实体上的多个@ManyToMany会导致交叉连接

在 JPA 中,我如何找到具有属性值的所有类型和具有属性值的 ManyTomany 相关实体?