DATAJPA-415 - Convert array parameter values to Collection if necessary.
In order to support query methods with array-typed parameters (e.g. parameters passed in as varargs) correctly we have to convert such an array into a collection. Previously we passed those parameters as is which led to Exceptions in EclipseLink and Hibernate, e.g. Hibernate: IllegalArgumentException: Encountered array-valued parameter binding, but was expecting [java.lang.Integer].
This commit is contained in:
committed by
Oliver Gierke
parent
b99508fbf9
commit
2636f59304
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,32 +36,26 @@ import javax.persistence.TemporalType;
|
||||
* required. The id is typed by the parameterizable superclass.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@Entity
|
||||
@NamedQuery(name = "User.findByEmailAddress", query = "SELECT u FROM User u WHERE u.emailAddress = ?1")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
@Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
private int age;
|
||||
private boolean active;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdAt;
|
||||
@Temporal(TemporalType.TIMESTAMP) private Date createdAt;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String emailAddress;
|
||||
@Column(nullable = false, unique = true) private String emailAddress;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<User> colleagues;
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) private Set<User> colleagues;
|
||||
|
||||
@ManyToMany
|
||||
private Set<Role> roles;
|
||||
@ManyToMany private Set<Role> roles;
|
||||
|
||||
@ManyToOne
|
||||
private User manager;
|
||||
@ManyToOne private User manager;
|
||||
|
||||
/**
|
||||
* Creates a new empty instance of {@code User}.
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Kevin Raymond
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:application-context.xml")
|
||||
@@ -1105,6 +1106,22 @@ public class UserRepositoryTests {
|
||||
assertThat(result, is(firstUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-415
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportModifyingQueryWithVarArgs() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
repository.updateUserActiveState(false, firstUser.getId(), secondUser.getId(), thirdUser.getId(),
|
||||
fourthUser.getId());
|
||||
|
||||
long expectedCount = repository.count();
|
||||
assertThat(repository.findByActiveFalse().size(), is((int) expectedCount));
|
||||
assertThat(repository.findByActiveTrue().size(), is((int) 0));
|
||||
}
|
||||
|
||||
private Page<User> executeSpecWithSort(Sort sort) {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
@@ -22,7 +22,9 @@ import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Query;
|
||||
@@ -84,6 +86,7 @@ public class ParameterBinderUnitTests {
|
||||
|
||||
User invalidWithTemporalTypeParameter(@Temporal String registerDate);
|
||||
|
||||
List<User> validWithVarArgs(Integer... ids);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -219,6 +222,21 @@ public class ParameterBinderUnitTests {
|
||||
new ParameterBinder(parameters, new Object[] { "foo", "" });
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-415
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void shouldAllowBindingOfVarArgs() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("validWithVarArgs", Integer[].class);
|
||||
JpaParameters parameters = new JpaParameters(method);
|
||||
Integer[] ids = new Integer[] { 1, 2, 3 };
|
||||
new ParameterBinder(parameters, new Object[] { ids }).bind(query);
|
||||
|
||||
verify(query).setParameter(eq(1), eq(Arrays.asList(1, 2, 3)));
|
||||
}
|
||||
|
||||
public SampleEntity findByEmbeddable(SampleEmbeddable embeddable) {
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2012 the original author or authors.
|
||||
* Copyright 2008-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,6 +39,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* Repository interface for {@code User}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User>,
|
||||
UserRepositoryCustom {
|
||||
@@ -270,4 +271,11 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
*/
|
||||
@Query("select u.firstname from User u where u.lastname = ?1")
|
||||
List<String> findFirstnamesByLastname(String lastname);
|
||||
|
||||
/**
|
||||
* @see DATAJPA-415
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update #{#entityName} u set u.active = :activeState where u.id in :ids")
|
||||
void updateUserActiveState(@Param("activeState") boolean activeState, @Param("ids") Integer... ids);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user