在用spring做count查询的时候,遇到了一个有点诡异的报错。首先,这里有一张表:
CREATE TABLE t_user (
user_id INT AUTO_INCREMENT PRIMARY KEY,
user_name VARCHAR(30),
password VARCHAR(32)
);
是一张很普通的数据表,并没有任何奇怪的地方。然后,配置好JPA之后(配置就不发了,想必遇到这个报错的人已经跑起来了),我写了这样一个repository:
public interface UserRegistry extends JpaRepository<User, Integer> {
long countByUserNameAndPassword(
String userName,
String password
);
}
这个看上去也没啥问题,但是运行的时候就报错了。一般来说这个问题就是配置没写对,但是IDEA能正常提示,而且官网也是这么写的:
interface UserRepository extends CrudRepository<User, Long> {
long countByLastname(String lastname);
}
用JpaRepository还是CrudRepository无关紧要,并不是这里的问题,而且我把这个方法注释掉之后就能跑了,也就是说,就是这个方法出了问题。问题是这怎么可能呢?我反反复复看了很长时间也没看出问题来,最后索性写了个老式的@Query
:
public interface UserRegistry extends JpaRepository<User, Integer> {
@Query("select count(userId) from User where userName = :userName and password = :password")
long countByUserNameAndPassword(
@Param("userName") String userName,
@Param("password") String password
);
}
这次能跑了。我突然想到,会不会是版本的问题,于是我跑去查了一下maven的依赖:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.3.2.RELEASE</version>
</dependency>
这个版本是2013年5月发布的,而官方文档是基于今年才发布的2.2.5编写的,中间整整差了一个大版本……估计问题就在版本上了。但是因为整个项目比较老,不敢随便升级(偷偷升级之后发现依赖崩了,赶紧回滚),于是放弃,倒回去写@query
。
但是在我印象中,这个写法好像已经有很久了,为了确定一下,我去查了一些资料,然后发现:
As of Spring Data 1.7.1.RELEASE you can do it with two different ways,
The new way, using query derivation for both count and delete queries.
The old way, Using @Query annotation.
也就是说,这种countBy的写法直到1.7.1才被支持,这个1.3.2的版本显然是不支持的。很有意思的是,1.7.1是2014年10月发布的,所以会给我一种已经用了很久的错觉。
但是这也太坑了吧。