java - Hibernate计数NamedQuery与同一实体的多对多关联

标签 java hibernate hql join named-query

我在同一 User 实体上有一个多对多关联,以允许用户关注其他用户。一切都按预期进行。

@ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(
    name = "user_follower", 
    joinColumns = {@JoinColumn(name="user")}, 
    inverseJoinColumns={@JoinColumn(name="follower")}
)
private List<User> followers;

@ManyToMany(mappedBy="followers", fetch = FetchType.LAZY)
private List<User> following;

我正在尝试获取分页的关注者数量。显然我可以使用 User.getFollowers.size() 来获取计数,但这相当昂贵。我决定使用命名查询来代替,因为这似乎是合理的做法。

@NamedQuery(
    name = "User.countFollowers", 
    query = "SELECT COUNT(u) FROM User u WHERE u.followers=:userId"
)

我知道这是不对的,因为我收到错误,但不知道如何修复它。这是堆栈跟踪:

Hibernate: /* User.countFollow */ select count(user0_.id) as col_0_0_ from user user0_ cross join user_follower followers1_, user user2_ where user0_.id=followers1_.user and followers1_.follower=user2_.id and .=?
DEBUG [2017-10-15 13:36:13,293] org.hibernate.SQL: /* User.countFollow */ select count(user0_.id) as col_0_0_ from user user0_ cross join user_follower followers1_, user user2_ where user0_.id=followers1_.user and followers1_.follower=user2_.id and .=?
WARN  [2017-10-15 13:36:13,345] org.hibernate.engine.jdbc.spi.SqlExceptionHelper: SQL Error: 1064, SQLState: 42000
ERROR [2017-10-15 13:36:13,346] org.hibernate.engine.jdbc.spi.SqlExceptionHelper: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1' at line 1
ERROR [2017-10-15 13:36:13,359] com.xxxx.xxxx.resources.Resource: There was a problem generating a response (SQLGrammarException). Please check the logs
! com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorExceptionxxxx: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1' at line 1
! at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
! at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
! at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
! at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
! at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
! at com.mysql.jdbc.Util.getInstance(Util.java:387)
! at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:939)
! at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
! at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
! at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
! at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
! at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
! at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
! at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1962)
! at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
! ... 77 common frames omitted
! Causing: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
! at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
! at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
! at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
! at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
! at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)
! at org.hibernate.loader.Loader.getResultSet(Loader.java:2115)
! at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1898)
! at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1874)
! at org.hibernate.loader.Loader.doQuery(Loader.java:919)
! at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
! at org.hibernate.loader.Loader.doList(Loader.java:2610)
! at org.hibernate.loader.Loader.doList(Loader.java:2593)
! at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2422)
! at org.hibernate.loader.Loader.list(Loader.java:2417)
! at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501)
! at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
! at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
! at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1339)
! at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
! at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:964)

感谢任何帮助。

最佳答案

这是用户和关注者之间的多对多关系,因此您的查询中应该有一个 JOIN。

SELECT COUNT(u) FROM User u JOIN u.followers f WHERE u.userId =:userId

这会查询特定用户 ID 的关注者数量。

关于java - Hibernate计数NamedQuery与同一实体的多对多关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46755103/

相关文章:

java - 如何将Drawable(ripple-drawable)设置为跨度的背景?

hibernate - hibernate 插件库未添加

java - 将 Java 构造函数与 Hibernate 查询结合使用

postgresql - 以与给定列表相同的顺序从 HQL 查询获取结果

java - BlobInput 的 Azure 函数绑定(bind)问题,没有任何错误

java - 我可以在 Java 中重命名已实现的方法吗?

java - 我可以绕过 hibernate 中的中间对象吗

java - 注释@Transactional。如何回滚?

java - 是否可以使用 Hibernate API 复制复杂的查询结果?

java - Wicket 应用程序、序列化和 Java 计时器