当我可以在 Spring JPA 中编写方法时,为什么需要 @Query

Why need @Query when I can write a method in Spring JPA

我刚开始使用 Spring JPA,我正在审查我的同事编写的代码。 我看到他一直在使用以下代码使用用户名查找登录对象:

public interface LoginDao extends JpaRepository<Login, Long> {
        @Query("SELECT u FROM Login u WHERE LOWER(u.username) = LOWER(:username)")
        Login findByUsername(@Param("username") String username);
}

他不能创建一个这样的方法吗:

@GET
@Path("{username}")
public Login getOne(@PathParam("username") String username) {
    Login login = loginDao.findOne(username);
    if (login == null) {
        throw new WebApplicationException(Response.Status.NOT_FOUND);
    } else {
        return login;
    }
}

使用@Query 而不是编写方法方法的基本优势是什么。还是我完全错了,两者的目的不同。

我个人不想在代码中编写查询。我认为混合使用 java 和 sql 查询会使代码看起来更难看。

我们的堆栈是 java、JPA、Jersey、JAX-RS、Postgreql、Spring Boot、Hibernate

此致

首先,这不是 SQL 查询,这是一个 JPQL 查询。如果 nativeQuery 属性设置为 true,这将是本机 SQL 查询,默认情况下并非如此。

使用 JPQL 创建查询非常好,您可以从 Hibernate 切换到 Eclipse Link 或其他 JPA 实现而不会出现问题。您还应该能够从 Postgres 切换到 MySQL、SQL 服务器...

如果您的同事使用 @Query(nativeQuery = true, value = "...") 创建查询,您必须开始担心,否则我觉得没问题。

其次,当您查看存储库声明时,您可以看到 Login 实体的 ID 字段的类型为 Long。这意味着 loginDao.findOne(..) 方法需要一个 Long 参数。可能是不是 username.

的代理键

这就是您的同事创建此新方法的原因:通过 Long 代理键以外的其他方式查找 Login 行。 (这里的用户名很可能是业务密钥,但我不知道您的应用程序。)


仅供参考:Spring 自动创建带有存储库方法签名的查询(派生查询)。例如:

public interface LoginDao extends JpaRepository<Login, Long> {
    Login findByUsername(String username);
}

Spring JPA 将自动创建一个查询以查找名为 username 的字段并使用它创建一个 WHERE 子句。

请注意,它与您同事的查询不同,因为它不会使用 LOWER 函数。

JPA 文档中关于那些派生查询的一些锚点:


关于您的标题的另一件事:

"Why need @Query when I can write a method in Spring JPA"

好吧,这个 @Query 在 Spring JPA 中编写了一个方法。 :^)

JPARepository 提出了一些受支持的关键字,这些关键字将根据您的实体自行编写查询。

如果我们正在寻找 JPARepository 提供的开箱即用的东西,@Query 很有用,例如 - 连接多个查询、编写本机查询等。

从你的代码片段来看,两者都会做同样的事情

更多信息可以参考-https://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/jpa.repositories.html