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:
Thomas Darimont
2013-10-21 15:40:43 +02:00
committed by Oliver Gierke
parent b99508fbf9
commit 2636f59304
5 changed files with 82 additions and 17 deletions

View File

@@ -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}.

View File

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

View File

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

View File

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