声明使用输入参数的属性作为查询参数的 Spring data JPA 查询的最简单方法是什么?
例如,假设我有一个实体类:
public class Person {
@Id
private long id;
@Column
private String forename;
@Column
private String surname;
}
还有另一堂课:
public class Name {
private String forename;
private String surname;
[constructor and getters]
}
...那么我想写一个Spring数据存储库,如下:
public interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person p where p.forename = ?1.forename and p.surname = ?1.surname")
findByName(Name name);
}
...但是 Spring data / JPA 不喜欢我在
?1
参数上指定属性名称。
最巧妙的替代方案是什么?
此链接将为您提供帮助:
Spring Data JPA
M1,支持 SpEL
表达式。类似的例子是:
@Query("select u from User u where u.firstname = :#{#customer.firstname}")
List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);
有关更多详细信息,请参阅:Spring Data JPA @Query 定义中的 SpEL 支持
定义带有签名的查询方法,如下所示。
@Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(@Param("surname") String lastname,
@Param("forename") String firstname);
}
有关更多详细信息,请查看 Spring Data JPA 参考
也可以通过接口默认的方法来解决:
@Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(@Param("surname") String lastname,
@Param("forename") String firstname);
default User findByName(Name name) {
return findByForenameAndSurname(name.getLastname(), name.getFirstname());
}
当然,您仍然可以公开可见实际的存储库功能...
你想要的东西是不可能的。您必须创建两个参数,并分别绑定它们:
select p from Person p where p.forename = :forename and p.surname = :surname
...
query.setParameter("forename", name.getForename());
query.setParameter("surname", name.getSurname());
你可以尝试这样的事情:
public interface PersonRepository extends CrudRepository<Person, Long> {
@Query("select p from Person AS p"
+ " ,Name AS n"
+ " where p.forename = n.forename "
+ " and p.surname = n.surname"
+ " and n = :name")
Set<Person>findByName(@Param("name") Name name);
}
如果我们使用 JpaRepository 那么它将在内部创建查询。
样品
findByLastnameAndFirstname(字符串姓氏,字符串名字)
findByLastnameOrFirstname(字符串姓氏,字符串名字)
findByStartDateBetween(日期 date1,Date2)
findById(int id)
注意
如果假设我们需要复杂的查询,那么我们需要编写手动查询,例如
@Query("SELECT salesOrder FROM SalesOrder salesOrder WHERE salesOrder.clientId=:clientId AND salesOrder.driver_username=:driver_username AND salesOrder.date>=:fdate AND salesOrder.date<=:tdate ")
@Transactional(readOnly=true)
List<SalesOrder> findAllSalesByDriver(@Param("clientId")Integer clientId, @Param("driver_username")String driver_username, @Param("fdate") Date fDate, @Param("tdate") Date tdate);
Spring Data JPA 的简单性在于它尝试从存储库中的函数名称进行解释,而不指定任何额外的
@Query
或 @Param
注释。
如果您提供完整的姓名,请尝试将其分解为名字和姓氏,然后使用类似这样的内容 -
HotelEntity findByName(String name);
我的 HotelEntity 确实包含字段 name,因此 JPA 尝试自行解释以推断我尝试查询的字段的名称,并在内部创建后续查询。 JPA 文档中的更多证据 -
更多详情 - 此处
您也在与
@Service
一起工作吗?因为如果您是,那么您可以将 @Autowired
PersonRepository
转换为 @Service
,然后在服务中只需调用 Name
类并使用 @CuriosMind... 提议的形式:
@Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(@Param("surname") String lastname,
@Param("forename") String firstname);
}
当从服务中的存储库调用方法时,您可以传递这些参数。
在 JPQL(Java 持久查询语言)中 - 您可以按照这个示例尝试
@Query("SELECT p FROM Product as p " +
"WHERE (:search IS null OR p.title LIKE %:#{#filter.search}%) " +
"AND (:companyId IS null OR p.company.id = :#{#filter.companyId}) " +
"AND (:categoryId IS null OR p.category.id = :#{#filter.categoryId}) "+
"AND (:colorId IS null OR p.color.id = :#{#filter.colorId}) "+
"AND (:maxPrice IS null OR p.newPrice < :#{#filter.maxPrice}) " +
"AND (:minPrice IS null OR p.newPrice >= :#{#filter.minPrice}) ")
List<Product> filterProduct(@Param("filter") Filter filter);
for using this, you can create a Repository for example this one:
Member findByEmail(String email);
List<Member> findByDate(Date date);
// custom query example and return a member
@Query("select m from Member m where m.username = :username and m.password=:password")
Member findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
@Autowired
private EntityManager entityManager;
@RequestMapping("/authors/{fname}/{lname}")
public List actionAutherMulti(@PathVariable("fname") String fname, @PathVariable("lname") String lname) {
return entityManager.createQuery("select A from Auther A WHERE A.firstName = ?1 AND A.lastName=?2")
.setParameter(1, fname)
.setParameter(2, lname)
.getResultList();
}