我刚刚开始使用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
此致
答案 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