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

时间:2017-06-20 12:07:14

标签: java spring hibernate spring-data-jpa jpql

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

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

此致

2 个答案:

答案 0 :(得分:1)

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

使用JPQL创建查询完全没问题,您将能够毫无问题地从Hibernate切换到Eclipse Link或其他JPA实现。您还应该能够从Postgres切换到MySQL,SQL Server ......

如果您的同事使用@Query(nativeQuery = true, value = "...")创建查询,您必须开始担心,否则它看起来不错。

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

这就是为什么你的同事创建了这个新方法:用Login代理键以外的方式查找Long行。 (这里的用户名很可能是一个商业密钥,但我不知道你的申请。)

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

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

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

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

JPA文档中有关这些派生查询的一些锚点:

关于你的头衔的另一件事:

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

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

答案 1 :(得分:1)

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

如果我们从JPARepository提供的@Query有用的内容中找到一些开箱即用的东西 - 加入多个查询,编写本机查询等。

从您的代码段开始,两者都会执行相同的操作

有关详细信息,请参阅 - https://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/jpa.repositories.html