spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param

Posted

技术标签:

【中文标题】spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param【英文标题】:spring-data-jpa repository use Collection as @Param in Query 【发布时间】:2016-04-13 17:28:35 【问题描述】:

我在使用 spring data jpa 存储库执行自定义查询时遇到问题。

@Query annitated 方法没有指定 List 类型的参数。

这里是实体类:

@Entity
@Table(name = "\"user\"")
public class User 
  @Id
  @GeneratedValue(generator = "increment")
  private long id;

  @Column(unique = true, nullable = false)
  private String mail;

  @ManyToMany(targetEntity = Interest.class, mappedBy = "users")
  private List<Interest> interests = new ArrayList<Interest>();
  ...
  ... setters and getters.

@Entity
@Table(name = "interest")
public class Interest 
  @Id
  @Column(name = "interest_name", nullable = false, unique = true)
  private String name;

  @ManyToMany(targetEntity = User.class, fetch = FetchType.LAZY)
  private List<User> users = new ArrayList<User>();
  ...
  ... setters and getters.

这里是查询:

@Repository
public interface UserRepository extends JpaRepository<User, Long> 
  @Query("select distinct u from User u where u <> :currentUser and
         u.interests in :currentInterests")
  List<User> getUsersWithSameInterests(@Param("currentUser") User user,
         @Param("currentInterests") List<Interest> interests);

我是这样用的:

@Autowired
private UserRepository userRepository;
  @Override
  public List<User> getUsersWithSameInterests(User user) 
    return userRepository.getUsersWithSameInterests(user, user.getInterests());
  

但是得到了

org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
.
.
.
Caused by: java.sql.SQLException: No value specified for parameter 2
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:896)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:885)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
at com.mysql.jdbc.PreparedStatement.checkAllParametersSet(PreparedStatement.java:2205)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2185)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2115)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1936)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
... 73 more

没有为参数 2 指定值,尽管第二个参数有有效值

【问题讨论】:

将 in 值放在 parentesis 之间,... u.interests in (:currentInterests) 看看它是否有效。如果命名为参数 ?1?2,您也可以尝试使用位置占位符。 不。括号和位置占位符都没有帮助。我马上就试过了。 :currentInterests 放在括号中。 【参考方案1】:
   Change the code as per below:

   Old Code:

   `@Repository
   public interface UserRepository extends JpaRepository<User, Long> 
   @Query("select distinct u from User u where u <> :currentUser and
         u.interests in :currentInterests")
   List<User> getUsersWithSameInterests(@Param("currentUser") User user,
         @Param("currentInterests") List<Interest> interests);
   `

   Updated Code:

   `@Repository
   public interface UserRepository extends JpaRepository<User, Long> 
   @Query("select distinct u from User u where u.user :currentUser 
           and u.interests in :currentInterests")
   List<User> getUsersWithSameInterests(@Param("currentUser") User user,
         @Param("currentInterests") List<Interest> interests);
  `    

【讨论】:

以上是关于spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param的主要内容,如果未能解决你的问题,请参考以下文章

spring-data-jpa 存储库模式与 Querydsl 查询模式有啥区别?

Spring-Data-Jpa 存储库 - 实体列名称上的下划线

使用 spring-data-jpa 自定义 ItemReader

spring-data-jpa

Spring-data-jpa 学习笔记

为什么Spring-Data-JPA Async无法正常工作?