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


75

声明使用输入参数的属性作为查询参数的Spring数据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数据/ JPA不喜欢我在?1参数上指定属性名称。

什么是最巧妙的选择?


它必须是动态的吗?为什么不能仅Name在from语句之后添加表?
Tulio F. 2012年

Name不一定是实体。
Kkkev

Answers:


157

该链接将为您提供帮助:支持SpEL表达式的Spring Data JPA M1。类似的例子是:

@Query("select u from User u where u.firstname = :#{#customer.firstname}")
List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);

https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions


1
这是spring-data-jpa 1.7.2 +,要求使用spring 4
chrismarx 2015年

客户在这里似乎必须是一个实体,评估POJO对我不起作用。
沙卡

没有尝试过pojo,我可以确认这至少与实体一起使用。别人没有提及他们遇到了问题,如果他们同时包含对象和附加参数(在这里看到评论) - spring.io/blog/2014/07/15/...
chrismarx

3
我可以确认我有同样的问题,甚至弹簧启动1.4 /弹簧4 /弹簧数据的JPA 1.10 -
chrismarx

嗨,星期天,它正在为我工​​作,我想问点事情。如果我在存储库中使用了Param,是否可以将Dtos与Param批注一起使用?
J. Abel,

19

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

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


2
那没有回答问题。相关的一点是,我想将输入参数的属性用作查询参数,而不是单独的输入参数。
Kkkev 2014年

糟糕,我误读了您的查询。我相信Spring Data JPA不提供支持(可能甚至是JDBC也可能没有;我在这里可能是错误的)。作为另一种选择(除了自定义存储库方法之外),您可以编写一个服务包装器方法,该方法将Person对象作为参数,并将相关参数传递给存储库方法。这种方法的优势在于,您期望的签名(通过Person对象)是完整的,并且您还可以使用Spring Data JPA提供的实现。
CuriosMind ...

10

您想要的是不可能的。您必须创建两个参数,并将其分别绑定:

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

1
大概这需要按照static.springsource.org/spring-data/data-jpa/docs/current/…在自定义存储库方法中实现
科奎夫2012年

1
我知道JPA的工作原理,但我不知道spring-data对您有什么作用,您必须自己做些什么。抱歉。
JB Nizet 2012年

8

您可以尝试如下操作:

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

1
@Kkkev这就是正确的,你需要做一个名称为实体这个解决方案
卡西

5

您也可以使用接口默认方法解决它:

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

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


2

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

1

您是否也在工作@Service?因为如果你是,那么你可以@AutowiredPersonRepository@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);
}

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


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

-3
@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();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.