带有参数属性的Spring数据JPA查询

问题描述 投票:0回答:11

声明使用输入参数的属性作为查询参数的 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 jpa spring-data spring-data-jpa
11个回答
267
投票

此链接将为您提供帮助:

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 支持


35
投票

定义带有签名的查询方法,如下所示。

@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 参考


12
投票

也可以通过接口默认的方法来解决:

 @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());
}

当然,您仍然可以公开可见实际的存储库功能...


11
投票

你想要的东西是不可能的。您必须创建两个参数,并分别绑定它们:

select p from Person p where p.forename = :forename and p.surname = :surname
...
query.setParameter("forename", name.getForename());
query.setParameter("surname", name.getSurname());

10
投票

你可以尝试这样的事情:

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);
    }

3
投票

如果我们使用 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);

3
投票

Spring Data JPA 的简单性在于它尝试从存储库中的函数名称进行解释,而不指定任何额外的

@Query
@Param
注释。 如果您提供完整的姓名,请尝试将其分解为名字和姓氏,然后使用类似这样的内容 -

HotelEntity findByName(String name);

我的 HotelEntity 确实包含字段 name,因此 JPA 尝试自行解释以推断我尝试查询的字段的名称,并在内部创建后续查询。 JPA 文档中的更多证据 -

更多详情 - 此处


1
投票

您也在与

@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);
}

当从服务中的存储库调用方法时,您可以传递这些参数。


0
投票

在 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);

-3
投票
    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);

-5
投票
@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();
    }
© www.soinside.com 2019 - 2024. All rights reserved.