天天看点

Spring @Query 简便使用和巨坑记录

@Query 用法有很多,暂时介绍一种使用

我们有两个表,article和author,article存author的id作为外键。但是返回时想取得author的名字,于是我们需要join。

最简单的方法自然是@Query自定义查询。我们先建立一个自定义的类ArticleInfo,它不与数据库中的任何表对应。然后建立一个ArticleInfoDAO的interface,继承自JpaRepository,定义@Query如下,其中ArticleEntity和AuthorEntity都是对应数据库中具体的某一个表的实体类:

@Query("select new com.demo.custommodel.ArticleInfo(a.articleId, a.authorId, a.editorId, a.moduleId, a.articleTitle, a.articleText, a.addTime, a.likeNum, au.authorName) from ArticleEntity a join AuthorEntity au on a.authorId = au.authorId")

List<ArticleInfo> findAllArticleInfo();

其中new是必须的,否则常见的不带new的写法,jpa返回的是List<Object>而不是List<ArticleInfo>,会导致无法从Object转换成你的自定义类而报错。

除此之外必须做的有:

1、自定义类ArticleInfo类名前加@Entity,表面这是一个实体类,用于@Query返回。

2、自定义类ArticleInfo可以有任何成员定义,无数种构造函数。但我们在@Query语句中写的new子句,其实是相当于调用这个类的构造函数,子句其中的参数必须有一个对应的,ArticleInfo类的构造函数。

坑在哪里呢,报错说ArticleInfo的构造参数不对应。

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.demo.custommodel.ArticleInfo]. Expected arguments are: int, int, int, int, java.lang.String, java.lang.String, java.util.Date, int, java.lang.String [select new com.demo.custommodel.ArticleInfo(a.articleId, a.authorId, a.editorId, a.moduleId, a.articleTitle, a.articleText, a.addTime, a.likeNum, au.authorName) from com.yourheadline.entity.ArticleEntity a join com.yourheadline.entity.AuthorEntity au on a.authorId = au.authorId]

    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]

    ... 66 common frames omitted

但是ArticleInfo的相应的构造函数怎么看都是对应的。结果最后问题出在了

"Expected arguments are: int, int, int, int, java.lang.String, java.lang.String, java.util.Date, int, java.lang.String"

的Date类型来自java.util.Date,而ArticleInfo中的Date是java.sql.Date。

继续阅读