@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。