Initial commit of Spring JPA repository abstraction.
Port of the Hades project whereas the JPA independent part resides in Spring Data Commons Core. Reflect changes refactorings for DATACMNS-2, DATACMNS-3, DATACMNS-4, DATACMNS-5, DATACMNS-6, DATACMNS-8, DATACMNS-9, DATAJPA-2.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Account extends AbstractPersistable<Long> {
|
||||
|
||||
private static final long serialVersionUID = -5719129808165758887L;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
|
||||
/**
|
||||
* Sample auditable role entity.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class AuditableRole extends AbstractAuditable<AuditableUser, Long> {
|
||||
|
||||
private static final long serialVersionUID = 5997359055260303863L;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
|
||||
/**
|
||||
* Sample auditable user to demonstrate working with
|
||||
* {@code AbstractAuditableEntity}. No declaration of an ID is necessary.
|
||||
* Furthermore no auditing information has to be declared explicitly.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
@NamedQuery(name = "AuditableUser.findByFirstname", query = "SELECT u FROM AuditableUser u WHERE u.firstname = ?1")
|
||||
public class AuditableUser extends AbstractAuditable<AuditableUser, Long> {
|
||||
|
||||
private static final long serialVersionUID = 7409344446795693011L;
|
||||
|
||||
private String firstname;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<AuditableRole> roles = new HashSet<AuditableRole>();
|
||||
|
||||
|
||||
public AuditableUser() {
|
||||
|
||||
this(null);
|
||||
}
|
||||
|
||||
|
||||
public AuditableUser(Long id) {
|
||||
|
||||
this.setId(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
|
||||
return firstname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
|
||||
public void addRole(AuditableRole role) {
|
||||
|
||||
this.roles.add(role);
|
||||
}
|
||||
|
||||
|
||||
public Set<AuditableRole> getRoles() {
|
||||
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
|
||||
|
||||
/**
|
||||
* Stub implementation for {@link AuditorAware}. Returns {@literal null} for the
|
||||
* current auditor.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditorAwareStub implements AuditorAware<User> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.synyx.hades.domain.auditing.AuditorAware#getCurrentAuditor()
|
||||
*/
|
||||
public User getCurrentAuditor() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
|
||||
/**
|
||||
* Example implementation of the very basic {@code Persistable} interface. The
|
||||
* id type is matching the typisation of the interface.
|
||||
* {@code Persitsable#isNew()} is implemented regarding the id as flag.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Role {
|
||||
|
||||
private static final long serialVersionUID = -8832631113344035104L;
|
||||
|
||||
private static final String PREFIX = "ROLE_";
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code Role}.
|
||||
*/
|
||||
public Role() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new preconfigured {@code Role}.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public Role(final String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.synyx.hades.jpa.support.Entity#getId()
|
||||
*/
|
||||
public Integer getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return PREFIX + name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.synyx.hades.jpa.support.Entity#isNew()
|
||||
*/
|
||||
public boolean isNew() {
|
||||
|
||||
return id == null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class SampleEntity {
|
||||
|
||||
@EmbeddedId
|
||||
protected SampleEntityPK id;
|
||||
|
||||
|
||||
protected SampleEntity() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity(String first, String second) {
|
||||
|
||||
this.id = new SampleEntityPK(first, second);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SampleEntity that = (SampleEntity) obj;
|
||||
|
||||
return this.id.equals(that.id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return id.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@Embeddable
|
||||
public class SampleEntityPK implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 231060947L;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String first;
|
||||
@Column(nullable = false)
|
||||
private String second;
|
||||
|
||||
|
||||
public SampleEntityPK() {
|
||||
|
||||
this.first = null;
|
||||
this.second = null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntityPK(String first, String second) {
|
||||
|
||||
Assert.notNull(first);
|
||||
Assert.notNull(second);
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SampleEntityPK that = (SampleEntityPK) obj;
|
||||
|
||||
return this.first.equals(that.first) && this.second.equals(that.second);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
result += 31 * first.hashCode();
|
||||
result += 31 * second.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Domain class representing a person emphasizing the use of
|
||||
* {@code AbstractEntity}. No declaration of an id is required. The id is typed
|
||||
* by the parameterizable superclass.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
@NamedQuery(name = "User.findByEmailAddress", query = "SELECT u FROM User u WHERE u.emailAddress = ?1")
|
||||
public class User {
|
||||
|
||||
private static final long serialVersionUID = 8653688953355455933L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String emailAddress;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<User> colleagues;
|
||||
|
||||
@ManyToMany
|
||||
private Set<Role> roles;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new empty instance of {@code User}.
|
||||
*/
|
||||
public User() {
|
||||
|
||||
this.roles = new HashSet<Role>();
|
||||
this.colleagues = new HashSet<User>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code User} with preinitialized values for
|
||||
* firstname, lastname and email address.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @param emailAddress
|
||||
*/
|
||||
public User(final String firstname, final String lastname,
|
||||
final String emailAddress) {
|
||||
|
||||
this();
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public Integer getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(Integer id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
|
||||
return firstname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the lastname.
|
||||
*
|
||||
* @return the lastname
|
||||
*/
|
||||
public String getLastname() {
|
||||
|
||||
return lastname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the lastname.
|
||||
*
|
||||
* @param lastname the lastname to set
|
||||
*/
|
||||
public void setLastname(String lastname) {
|
||||
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the email address.
|
||||
*
|
||||
* @return the emailAddress
|
||||
*/
|
||||
public String getEmailAddress() {
|
||||
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the email address.
|
||||
*
|
||||
* @param emailAddress the emailAddress to set
|
||||
*/
|
||||
public void setEmailAddress(String emailAddress) {
|
||||
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the user's roles.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public Set<Role> getRole() {
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives the user a role. Adding a role the user already owns is a no-op.
|
||||
*/
|
||||
public void addRole(Role role) {
|
||||
|
||||
roles.add(role);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revokes a role from a user.
|
||||
*
|
||||
* @param role
|
||||
*/
|
||||
public void removeRole(Role role) {
|
||||
|
||||
roles.remove(role);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the colleagues of the user.
|
||||
*
|
||||
* @return the colleagues
|
||||
*/
|
||||
public Set<User> getColleagues() {
|
||||
|
||||
return colleagues;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new colleague to the user. Adding the user himself as colleague is
|
||||
* a no-op.
|
||||
*
|
||||
* @param collegue
|
||||
*/
|
||||
public void addColleague(User collegue) {
|
||||
|
||||
// Prevent from adding the user himself as colleague.
|
||||
if (this.equals(collegue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
colleagues.add(collegue);
|
||||
collegue.getColleagues().add(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a colleague from the list of colleagues.
|
||||
*
|
||||
* @param colleague
|
||||
*/
|
||||
public void removeColleague(User colleague) {
|
||||
|
||||
colleagues.remove(colleague);
|
||||
colleague.getColleagues().remove(this);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!(obj instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
User that = (User) obj;
|
||||
|
||||
if (null == this.getId() || null == that.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getId().equals(that.getId());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return "User: " + getId() + ", " + getFirstname() + " " + getLastname()
|
||||
+ ", " + getEmailAddress();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
|
||||
/**
|
||||
* Collection of {@link Specification}s for a {@link User}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UserSpecifications {
|
||||
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasFirstname(final String firstname) {
|
||||
|
||||
return simplePropertySpec("firstname", firstname);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s lastname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasLastname(final String lastname) {
|
||||
|
||||
return simplePropertySpec("lastname", lastname);
|
||||
}
|
||||
|
||||
|
||||
private static <T> Specification<T> simplePropertySpec(
|
||||
final String property, final Object value) {
|
||||
|
||||
return new Specification<T>() {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
|
||||
return builder.equal(root.get(property), value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link AuditingBeanFactoryPostProcessor}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingBeanFactoryPostProcessorUnitTests {
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory;
|
||||
AuditingBeanFactoryPostProcessor processor;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
beanFactory =
|
||||
new XmlBeanFactory(new ClassPathResource("auditing/"
|
||||
+ getConfigFile()));
|
||||
|
||||
processor = new AuditingBeanFactoryPostProcessor();
|
||||
}
|
||||
|
||||
|
||||
protected String getConfigFile() {
|
||||
|
||||
return "auditing-bfpp-context.xml";
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testname() throws Exception {
|
||||
|
||||
processor.postProcessBeanFactory(beanFactory);
|
||||
|
||||
BeanDefinition definition =
|
||||
beanFactory.getBeanDefinition("entityManagerFactory");
|
||||
|
||||
assertTrue(Arrays
|
||||
.asList(definition.getDependsOn())
|
||||
.contains(
|
||||
AuditingBeanFactoryPostProcessor.BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Auditable;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableRole;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
import org.springframework.data.jpa.repository.sample.AuditableUserRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:auditing/auditing-entity-listener.xml")
|
||||
public class AuditingEntityListenerTests {
|
||||
|
||||
@Autowired
|
||||
AuditableUserRepository dao;
|
||||
|
||||
|
||||
@Test
|
||||
public void auditsRootEntityCorrectly() throws Exception {
|
||||
|
||||
AuditableUser user = new AuditableUser();
|
||||
dao.save(user);
|
||||
|
||||
assertDatesSet(user);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void auditsTransitiveEntitiesCorrectly() throws Exception {
|
||||
|
||||
AuditableRole role = new AuditableRole();
|
||||
role.setName("ADMIN");
|
||||
|
||||
AuditableUser user = new AuditableUser();
|
||||
user.addRole(role);
|
||||
dao.save(user);
|
||||
|
||||
assertDatesSet(user);
|
||||
assertDatesSet(role);
|
||||
}
|
||||
|
||||
|
||||
private void assertDatesSet(Auditable<?, ?> auditable) {
|
||||
|
||||
assertThat(auditable.getCreatedDate(), is(notNullValue()));
|
||||
assertThat(auditable.getLastModifiedDate(), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code AuditingEntityListener}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class AuditingEntityListenerUnitTests {
|
||||
|
||||
AuditingEntityListener<AuditableUser> auditionAdvice;
|
||||
AuditorAware<AuditableUser> auditorAware;
|
||||
|
||||
AuditableUser user;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
auditionAdvice = new AuditingEntityListener<AuditableUser>();
|
||||
|
||||
user = new AuditableUser();
|
||||
|
||||
auditorAware = mock(AuditorAware.class);
|
||||
when(auditorAware.getCurrentAuditor()).thenReturn(user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that the advice does not set auditor on the target entity if no
|
||||
* {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void doesNotSetAuditorIfNotConfigured() {
|
||||
|
||||
auditionAdvice.touch(user);
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getLastModifiedBy());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that the advice sets the auditor on the target entity if an
|
||||
* {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void setsAuditorIfConfigured() {
|
||||
|
||||
auditionAdvice.setAuditorAware(auditorAware);
|
||||
|
||||
auditionAdvice.touch(user);
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that the advice does not set modification information on creation
|
||||
* if the falg is set to {@code false}.
|
||||
*/
|
||||
@Test
|
||||
public void honoursModifiedOnCreationFlag() {
|
||||
|
||||
auditionAdvice.setAuditorAware(auditorAware);
|
||||
auditionAdvice.setModifyOnCreation(false);
|
||||
auditionAdvice.touch(user);
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getCreatedBy());
|
||||
|
||||
assertNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the advice only sets modification data if a not-new entity is
|
||||
* handled.
|
||||
*/
|
||||
@Test
|
||||
public void onlySetsModificationDataOnNotNewEntities() {
|
||||
|
||||
user = new AuditableUser(1L);
|
||||
|
||||
auditionAdvice.setAuditorAware(auditorAware);
|
||||
auditionAdvice.touch(user);
|
||||
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotSetTimeIfConfigured() throws Exception {
|
||||
|
||||
auditionAdvice.setDateTimeForNow(false);
|
||||
auditionAdvice.setAuditorAware(auditorAware);
|
||||
auditionAdvice.touch(user);
|
||||
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for the Hades {@code auditing} namespace element.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingNamespaceUnitTests extends
|
||||
AuditingBeanFactoryPostProcessorUnitTests {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.synyx.hades.domain.auditing.AuditingBeanFactoryPostProcessorUnitTest
|
||||
* #getConfigFile()
|
||||
*/
|
||||
@Override
|
||||
protected String getConfigFile() {
|
||||
|
||||
return "auditing-namespace-context.xml";
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void registersBeanDefinitions() throws Exception {
|
||||
|
||||
BeanDefinition definition =
|
||||
beanFactory.getBeanDefinition(AuditingEntityListener.class
|
||||
.getName());
|
||||
assertEquals(
|
||||
definition.getPropertyValues().getPropertyValue("auditorAware")
|
||||
.getValue(), new RuntimeBeanReference("auditorAware"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import org.junit.Ignore;
|
||||
|
||||
|
||||
/**
|
||||
* Testcase to run {@link org.synyx.hades.dao.UserDao} integration tests on top
|
||||
* of EclipseLink. So far not running as of an EclipseLink bug.
|
||||
*
|
||||
* @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=312132
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
// @ContextConfiguration(value = "classpath:eclipselink.xml", inheritLocations =
|
||||
// true)
|
||||
@Ignore
|
||||
public class EclipseLinkNamespaceUserRepositoryTests extends
|
||||
NamespaceUserRepositoryTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Use namespace context to run tests. Checks for existence of required
|
||||
* PostProcessors, too.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Eberhard Wolff
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml", inheritLocations = false)
|
||||
public class NamespaceUserRepositoryTests extends UserRepositoryTests {
|
||||
|
||||
@Autowired
|
||||
ListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@Test
|
||||
public void registersPostProcessors() {
|
||||
|
||||
hasAtLeastOneBeanOfType(PersistenceAnnotationBeanPostProcessor.class);
|
||||
hasAtLeastOneBeanOfType(PersistenceExceptionTranslationPostProcessor.class);
|
||||
}
|
||||
|
||||
|
||||
private void hasAtLeastOneBeanOfType(Class<?> beanType) {
|
||||
|
||||
Map<String, ?> beans = beanFactory.getBeansOfType(beanType);
|
||||
assertFalse(beans.entrySet().isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Simple test case launching an {@code ApplicationContext} to test
|
||||
* infrastructure configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:infrastructure.xml")
|
||||
public class ORMInfrastructureTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
/**
|
||||
* Tests, that the context got initialized and injected correctly.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void contextInitialized() throws Exception {
|
||||
|
||||
assertNotNull(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Testcase to run {@link org.synyx.hades.dao.UserDao} integration tests on top
|
||||
* of OpenJPA.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(value = "classpath:openjpa.xml", inheritLocations = true)
|
||||
public class OpenJpaNamespaceUserDaoTests extends
|
||||
NamespaceUserRepositoryTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for executing finders, thus testing various query lookup
|
||||
* strategies.
|
||||
*
|
||||
* @see QueryLookupStrategy
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml")
|
||||
@Transactional
|
||||
public class UserRepositoryFinderTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
|
||||
User firstUser, secondUser;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
// This one matches both criterias
|
||||
firstUser = new User();
|
||||
firstUser.setEmailAddress("foo");
|
||||
firstUser.setLastname("bar");
|
||||
firstUser.setFirstname("foobar");
|
||||
|
||||
userRepository.save(firstUser);
|
||||
|
||||
// This one matches only the second one
|
||||
secondUser = new User();
|
||||
secondUser.setEmailAddress("bar");
|
||||
secondUser.setLastname("foo");
|
||||
|
||||
userRepository.save(secondUser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests creation of a simple query.
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleCustomCreatedFinder() {
|
||||
|
||||
User user = userRepository.findByEmailAddressAndLastname("foo", "bar");
|
||||
assertEquals(firstUser, user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the DAO returns {@code null} for not found objects for finder
|
||||
* methods that return a single domain object.
|
||||
*/
|
||||
@Test
|
||||
public void returnsNullIfNothingFound() {
|
||||
|
||||
User user = userRepository.findByEmailAddress("foobar");
|
||||
assertEquals(null, user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests creation of a simple query consisting of {@code AND} and {@code OR}
|
||||
* parts.
|
||||
*/
|
||||
@Test
|
||||
public void testAndOrFinder() {
|
||||
|
||||
List<User> users =
|
||||
userRepository.findByEmailAddressAndLastnameOrFirstname("bar",
|
||||
"foo", "foobar");
|
||||
|
||||
assertNotNull(users);
|
||||
assertEquals(2, users.size());
|
||||
assertTrue(users.contains(firstUser));
|
||||
assertTrue(users.contains(secondUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesPagingMethodToPageCorrectly() throws Exception {
|
||||
|
||||
Page<User> page =
|
||||
userRepository
|
||||
.findByFirstname(new PageRequest(0, 20), "foobar");
|
||||
assertEquals(1, page.getNumberOfElements());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesPagingMethodToListCorrectly() throws Exception {
|
||||
|
||||
List<User> list =
|
||||
userRepository
|
||||
.findByFirstname("foobar", new PageRequest(0, 20));
|
||||
assertThat(list.size(), is(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.Sort.Direction.*;
|
||||
import static org.springframework.data.jpa.domain.Specifications.*;
|
||||
import static org.springframework.data.jpa.domain.sample.UserSpecifications.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.domain.sample.Role;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Base integration test class for {@code UserRepository}. Loads a basic
|
||||
* (non-namespace) Spring configuration file as well as Hibernate configuration
|
||||
* to execute tests.
|
||||
* <p>
|
||||
* To test further persistence providers subclass this class and provide a
|
||||
* custom provider configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "classpath:application-context.xml" })
|
||||
@Transactional
|
||||
public class UserRepositoryTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
// CUT
|
||||
@Autowired
|
||||
UserRepository repository;
|
||||
|
||||
// Test fixture
|
||||
User firstUser, secondUser, thirdUser;
|
||||
Integer id;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
firstUser = new User("Oliver", "Gierke", "gierke@synyx.de");
|
||||
secondUser = new User("Joachim", "Arrasz", "arrasz@synyx.de");
|
||||
thirdUser = new User("Dave", "Matthews", "no@email.com");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests creation of users.
|
||||
*/
|
||||
@Test
|
||||
public void testCreation() {
|
||||
|
||||
Query countQuery = em.createQuery("select count(u) from User u");
|
||||
Long before = (Long) countQuery.getSingleResult();
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
assertEquals(before + 3, countQuery.getSingleResult());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests reading a single user.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
User foundPerson = repository.findById(id);
|
||||
assertEquals(firstUser.getFirstname(), foundPerson.getFirstname());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts, that a call to {@code UserRepository#readId(Integer)} returns
|
||||
* {@code null} for invalid not {@code null} ids.
|
||||
*/
|
||||
@Test
|
||||
public void testReadByIdReturnsNullForNotFoundEntities() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
assertNull(repository.findById(id * 27));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void savesCollectionCorrectly() throws Exception {
|
||||
|
||||
List<User> result =
|
||||
repository
|
||||
.save(Arrays.asList(firstUser, secondUser, thirdUser));
|
||||
assertNotNull(result);
|
||||
assertThat(result.size(), is(3));
|
||||
assertThat(result, hasItems(firstUser, secondUser, thirdUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void savingNullCollectionIsNoOp() throws Exception {
|
||||
|
||||
List<User> result = repository.save((Collection<User>) null);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void savingEmptyCollectionIsNoOp() throws Exception {
|
||||
|
||||
List<User> result = repository.save(new ArrayList<User>());
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests updating a user.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
User foundPerson = repository.findById(id);
|
||||
foundPerson.setLastname("Schlicht");
|
||||
|
||||
User updatedPerson = repository.findById(id);
|
||||
assertEquals(foundPerson.getFirstname(), updatedPerson.getFirstname());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void existReturnsWhetherAnEntityCanBeLoaded() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
assertTrue(repository.exists(id));
|
||||
assertFalse(repository.exists(id * 27));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests deleting a user.
|
||||
*/
|
||||
@Test
|
||||
public void testDelete() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
repository.delete(firstUser);
|
||||
assertNull(repository.findById(id));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsAllSortedCorrectly() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
List<User> result = repository.findAll(new Sort(ASC, "lastname"));
|
||||
assertNotNull(result);
|
||||
assertThat(result.size(), is(3));
|
||||
assertThat(result.get(0), is(secondUser));
|
||||
assertThat(result.get(1), is(firstUser));
|
||||
assertThat(result.get(2), is(thirdUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteColletionOfEntities() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
long before = repository.count();
|
||||
|
||||
repository.delete(Arrays.asList(firstUser, secondUser));
|
||||
assertThat(repository.count(), is(before - 2));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteEmptyCollectionDoesNotDeleteAnything() {
|
||||
|
||||
assertDeleteCallDoesNotDeleteAnything(new ArrayList<User>());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteWithNullDoesNotDeleteAnything() throws Exception {
|
||||
|
||||
assertDeleteCallDoesNotDeleteAnything(null);
|
||||
}
|
||||
|
||||
|
||||
private void assertDeleteCallDoesNotDeleteAnything(List<User> collection) {
|
||||
|
||||
flushTestUsers();
|
||||
Long count = repository.count();
|
||||
|
||||
repository.delete(collection);
|
||||
assertEquals(count, repository.count());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesManipulatingQuery() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
repository.renameAllUsersTo("newLastname");
|
||||
|
||||
assertEquals(repository.count().intValue(),
|
||||
repository.findByLastname("newLastname").size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure no {@link NullPointerException} is being thrown.
|
||||
*
|
||||
* @see Ticket #110
|
||||
*/
|
||||
@Test
|
||||
public void testFinderInvocationWithNullParameter() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
repository.findByLastname(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests, that searching by the lastname of the reference user returns
|
||||
* exactly that instance.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testFindByLastname() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
List<User> byName = repository.findByLastname("Gierke");
|
||||
|
||||
assertTrue(byName.size() == 1);
|
||||
assertEquals(firstUser, byName.get(0));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests, that searching by the email address of the reference user returns
|
||||
* exactly that instance.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testFindByEmailAddress() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
User byName = repository.findByEmailAddress("gierke@synyx.de");
|
||||
|
||||
assertNotNull(byName);
|
||||
assertEquals(firstUser, byName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests reading all users.
|
||||
*/
|
||||
@Test
|
||||
public void testReadAll() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
List<User> reference = Arrays.asList(firstUser, secondUser);
|
||||
assertTrue(repository.findAll().containsAll(reference));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that all users get deleted by triggering
|
||||
* {@link UserDao#deleteAll()}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void deleteAll() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
repository.deleteAll();
|
||||
|
||||
assertEquals((Long) 0L, repository.count());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests cascading persistence.
|
||||
*/
|
||||
@Test
|
||||
public void testCascadesPersisting() {
|
||||
|
||||
// Create link prior to persisting
|
||||
firstUser.addColleague(secondUser);
|
||||
|
||||
// Persist
|
||||
flushTestUsers();
|
||||
|
||||
// Fetches first user from .. bdatabase
|
||||
User firstReferenceUser = repository.findById(firstUser.getId());
|
||||
assertEquals(firstUser, firstReferenceUser);
|
||||
|
||||
// Fetch colleagues and assert link
|
||||
Set<User> colleagues = firstReferenceUser.getColleagues();
|
||||
assertEquals(1, colleagues.size());
|
||||
assertTrue(colleagues.contains(secondUser));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests, that persisting a relationsship without cascade attributes throws
|
||||
* a {@code DataAccessException}.
|
||||
*/
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void testPreventsCascadingRolePersisting() {
|
||||
|
||||
firstUser.addRole(new Role("USER"));
|
||||
|
||||
flushTestUsers();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests cascading on {@literal merge} operation.
|
||||
*/
|
||||
@Test
|
||||
public void testMergingCascadesCollegueas() {
|
||||
|
||||
firstUser.addColleague(secondUser);
|
||||
flushTestUsers();
|
||||
|
||||
firstUser.addColleague(new User("Florian", "Hopf", "hopf@synyx.de"));
|
||||
firstUser = repository.save(firstUser);
|
||||
|
||||
User reference = repository.findById(firstUser.getId());
|
||||
Set<User> colleagues = reference.getColleagues();
|
||||
|
||||
assertNotNull(colleagues);
|
||||
assertEquals(2, colleagues.size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests, that the generic dao implements count correctly.
|
||||
*/
|
||||
@Test
|
||||
public void testCountsCorrectly() {
|
||||
|
||||
Long count = repository.count();
|
||||
|
||||
User user = new User();
|
||||
user.setEmailAddress("gierke@synyx.de");
|
||||
repository.save(user);
|
||||
|
||||
assertTrue(repository.count().equals(count + 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests invoking a method of a custom implementation of the DAO interface.
|
||||
*/
|
||||
@Test
|
||||
public void testInvocationOfCustomImplementation() {
|
||||
|
||||
repository.someCustomMethod(new User());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that overriding a finder method is recognized by the DAO
|
||||
* implementation. If an overriding method is found it will will be invoked
|
||||
* instead of the automatically generated finder.
|
||||
*/
|
||||
@Test
|
||||
public void testOverwritingFinder() {
|
||||
|
||||
repository.findByOverrridingMethod();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUsesHadesQueryAnnotation() {
|
||||
|
||||
assertEquals(null, repository.findByHadesQuery("gierke@synyx.de"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExecutionOfProjectingMethod() {
|
||||
|
||||
flushTestUsers();
|
||||
assertEquals(1, repository.countWithFirstname("Oliver").longValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesSpecificationCorrectly() {
|
||||
|
||||
flushTestUsers();
|
||||
assertThat(
|
||||
repository.findAll(where(userHasFirstname("Oliver"))).size(),
|
||||
is(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesSingleEntitySpecificationCorrectly() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
assertThat(repository.findOne(userHasFirstname("Oliver")),
|
||||
is(firstUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesCombinedSpecificationsCorrectly() {
|
||||
|
||||
flushTestUsers();
|
||||
Specification<User> spec =
|
||||
where(userHasFirstname("Oliver")).or(userHasLastname("Arrasz"));
|
||||
assertThat(repository.findAll(spec).size(), is(2));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesCombinedSpecificationsWithPageableCorrectly() {
|
||||
|
||||
flushTestUsers();
|
||||
Specification<User> spec =
|
||||
where(userHasFirstname("Oliver")).or(userHasLastname("Arrasz"));
|
||||
|
||||
Page<User> users = repository.findAll(spec, new PageRequest(0, 1));
|
||||
assertThat(users.getSize(), is(1));
|
||||
assertThat(users.hasPreviousPage(), is(false));
|
||||
assertThat(users.getTotalElements(), is(2L));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flushes test users to the database.
|
||||
*/
|
||||
private void flushTestUsers() {
|
||||
|
||||
firstUser = repository.save(firstUser);
|
||||
secondUser = repository.save(secondUser);
|
||||
thirdUser = repository.save(thirdUser);
|
||||
|
||||
repository.flush();
|
||||
|
||||
id = firstUser.getId();
|
||||
|
||||
assertThat(id, is(notNullValue()));
|
||||
assertThat(secondUser.getId(), is(notNullValue()));
|
||||
assertThat(thirdUser.getId(), is(notNullValue()));
|
||||
|
||||
assertThat(repository.exists(id), is(true));
|
||||
assertThat(repository.exists(secondUser.getId()), is(true));
|
||||
assertThat(repository.exists(thirdUser.getId()), is(true));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesMethodWithAnnotatedNamedParametersCorrectly()
|
||||
throws Exception {
|
||||
|
||||
firstUser = repository.save(firstUser);
|
||||
secondUser = repository.save(secondUser);
|
||||
|
||||
assertTrue(repository.findByLastnameOrFirstname("Oliver", "Arrasz")
|
||||
.containsAll(Arrays.asList(firstUser, secondUser)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void executesMethodWithNamedParametersCorrectly() throws Exception {
|
||||
|
||||
firstUser = repository.save(firstUser);
|
||||
secondUser = repository.save(secondUser);
|
||||
|
||||
assertThat(repository.findByLastnameOrFirstnameUnannotated("Oliver",
|
||||
"Arrasz"), hasItems(firstUser, secondUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesMethodWithNamedParametersCorrectlyOnMethodsWithQueryCreation()
|
||||
throws Exception {
|
||||
|
||||
firstUser = repository.save(firstUser);
|
||||
secondUser = repository.save(secondUser);
|
||||
|
||||
assertTrue(repository.findByFirstnameOrLastname("Oliver", "Arrasz")
|
||||
.containsAll(Arrays.asList(firstUser, secondUser)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesLikeAndOrderByCorrectly() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
List<User> result =
|
||||
repository.findByLastnameLikeOrderByFirstnameDesc("%r%");
|
||||
assertEquals(firstUser, result.get(0));
|
||||
assertEquals(secondUser, result.get(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesNotLikeCorrectly() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
List<User> result = repository.findByLastnameNotLike("%er%");
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(secondUser, thirdUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesSimpleNotCorrectly() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
List<User> result = repository.findByLastnameNot("Gierke");
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(secondUser, thirdUser));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsSameListIfNoSpecGiven() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
assertSameElements(repository.findAll(),
|
||||
repository.findAll((Specification<User>) null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsSameListIfNoSortIsGiven() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
assertSameElements(repository.findAll((Sort) null),
|
||||
repository.findAll());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsSamePageIfNoSpecGiven() throws Exception {
|
||||
|
||||
Pageable pageable = new PageRequest(0, 1);
|
||||
|
||||
flushTestUsers();
|
||||
assertEquals(repository.findAll(pageable),
|
||||
repository.findAll(null, pageable));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsAllAsPageIfNoPageableIsGiven() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
assertEquals(new PageImpl<User>(repository.findAll()),
|
||||
repository.findAll((Pageable) null));
|
||||
}
|
||||
|
||||
|
||||
private static <T> void assertSameElements(Collection<T> first,
|
||||
Collection<T> second) {
|
||||
|
||||
for (T element : first) {
|
||||
assertThat(element, isIn(second));
|
||||
}
|
||||
|
||||
for (T element : second) {
|
||||
assertThat(element, isIn(first));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void removeDetachedObject() throws Exception {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
em.detach(firstUser);
|
||||
repository.delete(firstUser);
|
||||
|
||||
assertThat(repository.count(), is(2L));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void executesPagedSpecificationsCorrectly() throws Exception {
|
||||
|
||||
Page<User> result = executeSpecWithSort(null);
|
||||
assertThat(result.getContent(),
|
||||
anyOf(hasItem(firstUser), hasItem(thirdUser)));
|
||||
assertThat(result.getContent(), not(hasItem(secondUser)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesPagedSpecificationsWithSortCorrectly() throws Exception {
|
||||
|
||||
Page<User> result =
|
||||
executeSpecWithSort(new Sort(Direction.ASC, "lastname"));
|
||||
|
||||
assertThat(result.getContent(), hasItem(firstUser));
|
||||
assertThat(result.getContent(), not(hasItem(secondUser)));
|
||||
assertThat(result.getContent(), not(hasItem(thirdUser)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesPagedSpecificationWithSortCorrectly2() throws Exception {
|
||||
|
||||
Page<User> result =
|
||||
executeSpecWithSort(new Sort(Direction.DESC, "lastname"));
|
||||
|
||||
assertThat(result.getContent(), hasItem(thirdUser));
|
||||
assertThat(result.getContent(), not(hasItem(secondUser)));
|
||||
assertThat(result.getContent(), not(hasItem(firstUser)));
|
||||
}
|
||||
|
||||
|
||||
private Page<User> executeSpecWithSort(Sort sort) {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
Specification<User> spec =
|
||||
where(userHasFirstname("Oliver")).or(
|
||||
userHasLastname("Matthews"));
|
||||
|
||||
Page<User> result =
|
||||
repository.findAll(spec, new PageRequest(0, 1, sort));
|
||||
assertThat(result.getTotalElements(), is(2L));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.repository.sample.AuditableUserRepository;
|
||||
import org.springframework.data.jpa.repository.sample.RoleRepository;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for integration test for namespace configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractRepositoryConfigTests {
|
||||
|
||||
@Autowired(required = false)
|
||||
UserRepository userRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
RoleRepository roleRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
AuditableUserRepository auditableUserRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that context creation detects 3 DAO beans.
|
||||
*/
|
||||
@Test
|
||||
public void testContextCreation() {
|
||||
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNotNull(auditableUserRepository);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.repository.custom.UserCustomExtendedRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to exclude DAO interfaces from being picked up by Hades and thus
|
||||
* in consequence getting an instance being created.
|
||||
* <p>
|
||||
* This will typically be used when providing an extended base interface for all
|
||||
* DAOs in combination with a custom DAO base class to implement methods
|
||||
* declared in that intermediate interface. In this case you typically derive
|
||||
* your concrete DAO interfaces from the intermediate one but don't want Hades
|
||||
* to create a Spring bean for the intermediate interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-customfactory-context.xml")
|
||||
public class CustomRepositoryFactoryConfigTests {
|
||||
|
||||
@Autowired(required = false)
|
||||
UserCustomExtendedRepository userRepository;
|
||||
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testCustomFactoryUsed() {
|
||||
|
||||
Assert.notNull(userRepository);
|
||||
userRepository.customMethod(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for XML configuration of {@link QueryLookupStrategy.Key}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:config/lookup-strategies-context.xml")
|
||||
public class QueryLookupStrategyTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
/**
|
||||
* Assert that {@link QueryLookupStrategy#USE_DECLARED_QUERY} is being set
|
||||
* on the factory if configured.
|
||||
*/
|
||||
@Test
|
||||
public void assertUseDeclaredQuery() {
|
||||
|
||||
JpaRepositoryFactoryBean<?> factory =
|
||||
context.getBean("&roleRepository",
|
||||
JpaRepositoryFactoryBean.class);
|
||||
|
||||
assertEquals(Key.USE_DECLARED_QUERY,
|
||||
getField(factory, "queryLookupStrategyKey"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test to test DAO auto configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-autoconfig-context.xml")
|
||||
public class RepositoryAutoConfigTests extends
|
||||
AbstractRepositoryConfigTests {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for DAO namespace configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml")
|
||||
public class RepositoryConfigTests extends AbstractRepositoryConfigTests {
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test to test
|
||||
* {@link org.springframework.core.type.filter.TypeFilter} integration into
|
||||
* namespace.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-autoconfig-typefilter-context.xml")
|
||||
public class TypeFilterConfigTest extends
|
||||
AbstractRepositoryConfigTests {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seeorg.synyx.hades.dao.config.AbstractDaoConfigIntegrationTest#
|
||||
* testContextCreation()
|
||||
*/
|
||||
@Override
|
||||
public void testContextCreation() {
|
||||
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNull(auditableUserRepository);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Test cases for configuration support classes.</body>
|
||||
</html>
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Sample custom DAO base class implementing common custom functionality for all
|
||||
* derived DAO instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepository<T, ID extends Serializable> extends
|
||||
SimpleJpaRepository<T, ID> implements CustomGenericRepository<T, ID> {
|
||||
|
||||
/**
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepository(Class<T> domainClass,
|
||||
EntityManager entityManager) {
|
||||
|
||||
super(domainClass, entityManager);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.synyx.hades.customimpl.CustomExtendedGenericDao#customMethod(java
|
||||
* .io.Serializable)
|
||||
*/
|
||||
public T customMethod(ID id) {
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
"Forced exception for testing purposes.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
|
||||
import org.springframework.data.repository.support.RepositorySupport;
|
||||
|
||||
|
||||
/**
|
||||
* Sample implementation of a custom {@link JpaRepositoryFactory} to use
|
||||
* a custom repository base class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepositoryFactory extends
|
||||
JpaRepositoryFactory {
|
||||
|
||||
/**
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepositoryFactory(EntityManager entityManager) {
|
||||
|
||||
super(entityManager);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.GenericJpaRepositoryFactory
|
||||
* #getTargetRepository(java.lang.Class, javax.persistence.EntityManager)
|
||||
*/
|
||||
@Override
|
||||
protected <T, ID extends Serializable> RepositorySupport<T, ID> getTargetRepository(
|
||||
Class<T> domainClass, EntityManager em) {
|
||||
|
||||
return new CustomGenericJpaRepository<T, ID>(domainClass, em);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.GenericJpaRepositoryFactory
|
||||
* #getRepositoryClass()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Class<? extends RepositorySupport> getRepositoryClass() {
|
||||
|
||||
return CustomGenericJpaRepository.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.custom;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.support.RepositoryFactorySupport;
|
||||
|
||||
|
||||
/**
|
||||
* {@link GenericDaoFactoryBean} to return a custom DAO base class.
|
||||
*
|
||||
* @author Gil Markham
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepositoryFactoryBean<T extends JpaRepository<?, ?>>
|
||||
extends JpaRepositoryFactoryBean<T> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.
|
||||
* GenericJpaRepositoryFactoryBean#getFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
|
||||
|
||||
return new CustomGenericJpaRepositoryFactory(em);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
|
||||
/**
|
||||
* Extension of {@link Repository} to be added on a custom repository
|
||||
* base class. This tests the facility to implement custom base class
|
||||
* functionality for all repository instances derived from this interface and
|
||||
* implementation base class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface CustomGenericRepository<T, ID extends Serializable> extends
|
||||
JpaRepository<T, ID> {
|
||||
|
||||
/**
|
||||
* Custom sample method.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
T customMethod(ID id);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.custom;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom Extended DAO interface for a {@code User}. This relies on the custom
|
||||
* intermediate DAO interface {@link CustomGenericRepository}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface UserCustomExtendedRepository extends CustomGenericRepository<User, Integer> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryExecution}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaQueryExecutionUnitTests {
|
||||
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
AbstractJpaQuery jpaQuery;
|
||||
@Mock
|
||||
ParameterBinder binder;
|
||||
@Mock
|
||||
Query query;
|
||||
|
||||
Method method;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
method = Dummy.class.getMethod("voidMethod");
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullQuery() {
|
||||
|
||||
new StubQueryExecution().execute(null, binder);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullBinder() throws Exception {
|
||||
|
||||
new StubQueryExecution().execute(jpaQuery, null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void transformsNoResultExceptionToNull() {
|
||||
|
||||
assertThat(new JpaQueryExecution() {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query,
|
||||
ParameterBinder binder) {
|
||||
|
||||
throw new NoResultException();
|
||||
}
|
||||
}.execute(jpaQuery, binder), is(nullValue()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void modifyingExecutionClearsEntityManagerIfSet() {
|
||||
|
||||
Query param = any();
|
||||
when(binder.bind(param)).thenReturn(query);
|
||||
when(query.executeUpdate()).thenReturn(0);
|
||||
|
||||
ModifyingExecution execution = new ModifyingExecution(method, em);
|
||||
execution.execute(jpaQuery, binder);
|
||||
|
||||
verify(em, times(1)).clear();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsMethodReturnTypesForModifyingQuery() throws Exception {
|
||||
|
||||
new ModifyingExecution(Dummy.class.getMethod("voidMethod"), em);
|
||||
new ModifyingExecution(Dummy.class.getMethod("intMethod"), em);
|
||||
new ModifyingExecution(Dummy.class.getMethod("integerMethod"), em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void modifyingExecutionRejectsNonIntegerOrVoidReturnType()
|
||||
throws Exception {
|
||||
|
||||
new ModifyingExecution(Dummy.class.getMethod("longMethod"), em);
|
||||
}
|
||||
|
||||
static class StubQueryExecution extends JpaQueryExecution {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query,
|
||||
ParameterBinder binder) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static interface Dummy {
|
||||
|
||||
void voidMethod();
|
||||
|
||||
|
||||
int intMethod();
|
||||
|
||||
|
||||
Integer integerMethod();
|
||||
|
||||
|
||||
Long longMethod();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.CollectionExecution;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryMethod}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaQueryMethodUnitTests {
|
||||
|
||||
static final Class<?> DOMAIN_CLASS = User.class;
|
||||
static final String METHOD_NAME = "findByFirstname";
|
||||
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
|
||||
Method daoMethod, invalidReturnType, pageableAndSort, pageableTwice,
|
||||
sortableTwice, modifyingMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
daoMethod =
|
||||
UserRepository.class.getMethod("findByLastname", String.class);
|
||||
|
||||
invalidReturnType =
|
||||
InvalidDao.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class);
|
||||
pageableAndSort =
|
||||
InvalidDao.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class, Sort.class);
|
||||
pageableTwice =
|
||||
InvalidDao.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class, Pageable.class);
|
||||
|
||||
sortableTwice =
|
||||
InvalidDao.class.getMethod(METHOD_NAME, String.class,
|
||||
Sort.class, Sort.class);
|
||||
modifyingMethod =
|
||||
UserRepository.class
|
||||
.getMethod("renameAllUsersTo", String.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
|
||||
assertEquals("User.findByLastname", method.getNamedQueryName());
|
||||
assertThat(method.getExecution(), is(CollectionExecution.class));
|
||||
assertEquals("select x from User x where x.lastname = ?1",
|
||||
new QueryCreator(method).constructQuery());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullDaoMethod() {
|
||||
|
||||
new JpaQueryMethod(null, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullEntityManager() {
|
||||
|
||||
new JpaQueryMethod(daoMethod, extractor, null);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullQueryExtractor() {
|
||||
|
||||
new JpaQueryMethod(daoMethod, null, em);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsCorrectName() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
assertEquals(daoMethod.getName(), method.getName());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsQueryIfAvailable() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
|
||||
assertNull(method.getAnnotatedQuery());
|
||||
|
||||
Method daoMethod =
|
||||
UserRepository.class
|
||||
.getMethod("findByHadesQuery", String.class);
|
||||
|
||||
assertNotNull(new JpaQueryMethod(daoMethod, extractor, em)
|
||||
.getAnnotatedQuery());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsCorrectDomainClassName() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
assertEquals(DOMAIN_CLASS, method.getDomainClass());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsCorrectNumberOfParameters() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
assertTrue(method.isCorrectNumberOfParameters(daoMethod
|
||||
.getParameterTypes().length));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvalidReturntypeOnPagebleFinder() {
|
||||
|
||||
new JpaQueryMethod(invalidReturnType, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsPageableAndSortInFinderMethod() {
|
||||
|
||||
new JpaQueryMethod(pageableAndSort, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoPageableParameters() {
|
||||
|
||||
new JpaQueryMethod(pageableTwice, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoSortableParameters() {
|
||||
|
||||
new JpaQueryMethod(sortableTwice, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsPageablesOnPersistenceProvidersNotExtractingQueries()
|
||||
throws Exception {
|
||||
|
||||
Method method =
|
||||
UserRepository.class.getMethod("findByFirstname",
|
||||
Pageable.class, String.class);
|
||||
|
||||
when(extractor.canExtractQuery()).thenReturn(false);
|
||||
|
||||
new JpaQueryMethod(method, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void recognizesModifyingMethod() {
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(modifyingMethod, extractor, em);
|
||||
assertTrue(method.isModifyingQuery());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithPageable() throws Exception {
|
||||
|
||||
Method method =
|
||||
InvalidDao.class.getMethod("updateMethod", String.class,
|
||||
Pageable.class);
|
||||
|
||||
new JpaQueryMethod(method, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithSort() throws Exception {
|
||||
|
||||
Method method =
|
||||
InvalidDao.class.getMethod("updateMethod", String.class,
|
||||
Sort.class);
|
||||
|
||||
new JpaQueryMethod(method, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void discoversHintsCorrectly() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(daoMethod, extractor, em);
|
||||
List<QueryHint> hints = method.getHints();
|
||||
|
||||
assertNotNull(hints);
|
||||
assertThat(hints.get(0).name(), is("foo"));
|
||||
assertThat(hints.get(0).value(), is("bar"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to define invalid DAO methods for testing.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static interface InvalidDao {
|
||||
|
||||
// Invalid return type
|
||||
User findByFirstname(String firstname, Pageable pageable);
|
||||
|
||||
|
||||
// Should not use Pageable *and* Sort
|
||||
Page<User> findByFirstname(String firstname, Pageable pageable,
|
||||
Sort sort);
|
||||
|
||||
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Pageable first,
|
||||
Pageable second);
|
||||
|
||||
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Sort first, Sort second);
|
||||
|
||||
|
||||
// Not backed by a named query or @Query annotation
|
||||
@Modifying
|
||||
void updateMethod(String firstname);
|
||||
|
||||
|
||||
// Modifying and Pageable is not allowed
|
||||
@Modifying
|
||||
Page<String> updateMethod(String firstname, Pageable pageable);
|
||||
|
||||
|
||||
// Modifying and Sort is not allowed
|
||||
@Modifying
|
||||
void updateMethod(String firstname, Sort sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.query.QueryCreatorUnitTests.SampleEmbeddable;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link ParameterBinder}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ParameterBinderUnitTests {
|
||||
|
||||
private Method valid;
|
||||
|
||||
@Mock
|
||||
private Query query;
|
||||
private Method useIndexedParameters;
|
||||
private Method indexedParametersWithSort;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
valid = SampleDao.class.getMethod("valid", String.class);
|
||||
|
||||
useIndexedParameters =
|
||||
SampleDao.class.getMethod("useIndexedParameters", String.class);
|
||||
indexedParametersWithSort =
|
||||
SampleDao.class.getMethod("indexedParameterWithSort",
|
||||
String.class, Sort.class);
|
||||
}
|
||||
|
||||
static class User {
|
||||
|
||||
}
|
||||
|
||||
static interface SampleDao {
|
||||
|
||||
User useIndexedParameters(String lastname);
|
||||
|
||||
|
||||
User indexedParameterWithSort(String lastname, Sort sort);
|
||||
|
||||
|
||||
User valid(@Param("username") String username);
|
||||
|
||||
|
||||
User validWithPageable(@Param("username") String username,
|
||||
Pageable pageable);
|
||||
|
||||
|
||||
User validWithSort(@Param("username") String username, Sort sort);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToManyParameters() throws Exception {
|
||||
|
||||
new ParameterBinder(new Parameters(valid),
|
||||
new Object[] { "foo", "bar" });
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullParameters() throws Exception {
|
||||
|
||||
new ParameterBinder(new Parameters(valid), (Object[]) null);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToLittleParameters() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
|
||||
Parameters parameters = new Parameters(valid);
|
||||
new ParameterBinder(parameters);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void returnsNullIfNoPageableWasProvided() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
|
||||
Method method =
|
||||
SampleDao.class.getMethod("validWithPageable", String.class,
|
||||
Pageable.class);
|
||||
|
||||
Parameters parameters = new Parameters(method);
|
||||
ParameterBinder binder =
|
||||
new ParameterBinder(parameters, new Object[] { "foo", null });
|
||||
|
||||
assertThat(binder.getPageable(), is(nullValue()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindWorksWithNullForSort() throws Exception {
|
||||
|
||||
Method validWithSort =
|
||||
SampleDao.class.getMethod("validWithSort", String.class,
|
||||
Sort.class);
|
||||
|
||||
new ParameterBinder(new Parameters(validWithSort), new Object[] {
|
||||
"foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindWorksWithNullForPageable() throws Exception {
|
||||
|
||||
Method validWithPageable =
|
||||
SampleDao.class.getMethod("validWithPageable", String.class,
|
||||
Pageable.class);
|
||||
|
||||
new ParameterBinder(new Parameters(validWithPageable), new Object[] {
|
||||
"foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void usesIndexedParametersIfNoParamAnnotationPresent()
|
||||
throws Exception {
|
||||
|
||||
new ParameterBinder(new Parameters(useIndexedParameters),
|
||||
new Object[] { "foo" }).bind(query);
|
||||
verify(query).setParameter(eq(1), anyObject());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void usesParameterNameIfAnnotated() throws Exception {
|
||||
|
||||
when(query.setParameter(eq("username"), anyObject())).thenReturn(query);
|
||||
new ParameterBinder(new Parameters(valid), new Object[] { "foo" }) {
|
||||
|
||||
@Override
|
||||
boolean hasNamedParameter(Query query) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}.bind(query);
|
||||
verify(query).setParameter(eq("username"), anyObject());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindsEmbeddableCorrectly() throws Exception {
|
||||
|
||||
Method method =
|
||||
QueryCreatorUnitTests.class.getMethod("findByEmbeddable",
|
||||
SampleEmbeddable.class);
|
||||
Parameters parameters = new Parameters(method);
|
||||
SampleEmbeddable embeddable = new SampleEmbeddable();
|
||||
|
||||
new ParameterBinder(parameters, new Object[] { embeddable })
|
||||
.bind(query);
|
||||
|
||||
verify(query).setParameter(1, embeddable);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindsSortForIndexedParameters() throws Exception {
|
||||
|
||||
Sort sort = new Sort("name");
|
||||
ParameterBinder binder =
|
||||
new ParameterBinder(new Parameters(indexedParametersWithSort),
|
||||
new Object[] { "name", sort });
|
||||
assertThat(binder.getSort(), is(sort));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryMethodUnitTests.InvalidDao;
|
||||
import org.springframework.data.repository.query.QueryCreationException;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryCreator}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QueryCreatorUnitTests {
|
||||
|
||||
private Method method;
|
||||
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
method =
|
||||
QueryCreatorUnitTests.class.getMethod(
|
||||
"findByFirstnameAndMethod", String.class);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = QueryCreationException.class)
|
||||
public void rejectsInvalidProperty() throws Exception {
|
||||
|
||||
JpaQueryMethod finderMethod = new JpaQueryMethod(method, extractor, em);
|
||||
new QueryCreator(finderMethod).constructQuery();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void splitsKeywordsCorrectly() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
|
||||
method =
|
||||
QueryCreatorUnitTests.class.getMethod(
|
||||
"findByNameOrOrganization", String.class, String.class);
|
||||
|
||||
assertCreatesQueryForMethod(
|
||||
"where x.name = :name or x.organization = :organization",
|
||||
method);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws NoSuchMethodException
|
||||
* @throws SecurityException
|
||||
* @see #265
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void createsQueryWithEmbeddableCorrectly() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
|
||||
method =
|
||||
getClass()
|
||||
.getMethod("findByEmbeddable", SampleEmbeddable.class);
|
||||
|
||||
assertCreatesQueryForMethod("where x.embeddable = :embeddable", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createsQueryWithBetweenKeywordCorrectly() throws Exception {
|
||||
|
||||
method =
|
||||
getClass().getMethod("findByStartDateBetweenAndName",
|
||||
Date.class, Date.class, String.class);
|
||||
|
||||
assertCreatesQueryForMethod(
|
||||
"where x.startDate between :first and :second and x.name = :name",
|
||||
method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createsQueryWithLessThanKeywordCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByAgeLessThan", int.class);
|
||||
|
||||
assertCreatesQueryForMethod("where x.age < :age", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createsQueryWithGreaterThanKeywordCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByAgeGreaterThan", int.class);
|
||||
|
||||
assertCreatesQueryForMethod("where x.age > :age", method);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithoutBacking()
|
||||
throws SecurityException, NoSuchMethodException {
|
||||
|
||||
Method invalidModifyingMethod =
|
||||
InvalidDao.class.getMethod("updateMethod", String.class);
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(invalidModifyingMethod, extractor, em);
|
||||
|
||||
new QueryCreator(method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesLikeOperatorCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByNameLike", String.class);
|
||||
assertCreatesQueryForMethod("where x.name like :name", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesNotOperatorCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByNameNot", String.class);
|
||||
assertCreatesQueryForMethod("where x.name <> :name", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesNotNullOperatorCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByNameNotNull");
|
||||
assertCreatesQueryForMethod("where x.name is not null", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesLikeCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByNameLike", String.class);
|
||||
assertCreatesQueryForMethod("where x.name like :name", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesNotLikeCorrectly() throws Exception {
|
||||
|
||||
method = getClass().getMethod("findByNameNotLike", String.class);
|
||||
assertCreatesQueryForMethod("where x.name not like :name", method);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parsesOrderByClauseCorrectly() throws Exception {
|
||||
|
||||
method =
|
||||
getClass().getMethod("findByNameOrderByOrganizationDesc",
|
||||
String.class);
|
||||
assertCreatesQueryForMethod(
|
||||
"where x.name = :name order by x.organization desc", method);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the query created for the given {@link Method} results in a
|
||||
* query ending with the given {@link String}.
|
||||
*
|
||||
* @param queryEnd
|
||||
* @param method
|
||||
*/
|
||||
private void assertCreatesQueryForMethod(String queryEnd, Method method) {
|
||||
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, extractor, em);
|
||||
String result = new QueryCreator(queryMethod).constructQuery();
|
||||
assertThat(result, endsWith(queryEnd));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sample method to test failing query creation.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public User findByFirstnameAndMethod(String firstname) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A method to check that query keyowrds are considered correctly. The
|
||||
* {@link QueryCreator} must not detect the {@code Or} in
|
||||
* {@code Organization} as keyword.
|
||||
*
|
||||
* @param name
|
||||
* @param organization
|
||||
* @return
|
||||
*/
|
||||
public SampleEntity findByNameOrOrganization(String name,
|
||||
String organization) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sample method to create a finder query for that references an
|
||||
* {@link Embeddable}.
|
||||
*
|
||||
* @see #265
|
||||
* @param embeddable
|
||||
* @return
|
||||
*/
|
||||
public SampleEntity findByEmbeddable(SampleEmbeddable embeddable) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByStartDateBetweenAndName(Date first, Date second,
|
||||
String name) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByAgeLessThan(int age) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByAgeGreaterThan(int age) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByNameLike(String name) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByNameNotLike(String name) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByNameNot(String name) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByNameNotNull() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByNameOrderByOrganizationDesc(String name) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample class for keyword split check.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
static class SampleEntity {
|
||||
|
||||
private String organization;
|
||||
private String name;
|
||||
|
||||
private Date startDate;
|
||||
private int age;
|
||||
|
||||
private SampleEmbeddable embeddable;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
@SuppressWarnings("unused")
|
||||
static class SampleEmbeddable {
|
||||
|
||||
private String foo;
|
||||
private String bar;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryUtils}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class QueryUtilsUnitTests {
|
||||
|
||||
static final String QUERY = "select u from User u";
|
||||
static final String FQ_QUERY =
|
||||
"select u from org.synyx.hades.domain.User$Foo_Bar u";
|
||||
static final String SIMPLE_QUERY = "from User u";
|
||||
static final String COUNT_QUERY = "select count(u) from User u";
|
||||
|
||||
static final String QUERY_WITH_AS =
|
||||
"select u from User as u where u.username = ?";
|
||||
|
||||
static final Matcher<String> IS_U = is("u");
|
||||
|
||||
|
||||
@Test
|
||||
public void createsCountQueryCorrectly() throws Exception {
|
||||
|
||||
assertCountQuery(QUERY, COUNT_QUERY);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #303
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueriesCorrectlyForCapitalLetterJPQL() {
|
||||
|
||||
assertCountQuery("FROM User u WHERE u.foo.bar = ?",
|
||||
"select count(u) FROM User u WHERE u.foo.bar = ?");
|
||||
|
||||
assertCountQuery("SELECT u FROM User u where u.foo.bar = ?",
|
||||
"select count(u) FROM User u where u.foo.bar = ?");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForDistinctQueries() throws Exception {
|
||||
|
||||
assertCountQuery("select distinct u from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForConstructorQueries() throws Exception {
|
||||
|
||||
assertCountQuery(
|
||||
"select distinct new User(u.name) from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForJoins() throws Exception {
|
||||
|
||||
assertCountQuery(
|
||||
"select distinct new User(u.name) from User u left outer join u.roles r WHERE r = ?",
|
||||
"select count(distinct u) from User u left outer join u.roles r WHERE r = ?");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForQueriesWithSubSelects() throws Exception {
|
||||
|
||||
assertCountQuery(
|
||||
"select u from User u left outer join u.roles r where r in (select r from Role)",
|
||||
"select count(u) from User u left outer join u.roles r where r in (select r from Role)");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #355
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForAliasesCorrectly() throws Exception {
|
||||
|
||||
assertCountQuery("select u from User as u",
|
||||
"select count(u) from User as u");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsShortJpaSyntax() throws Exception {
|
||||
|
||||
assertCountQuery(SIMPLE_QUERY, COUNT_QUERY);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsAliasCorrectly() throws Exception {
|
||||
|
||||
assertThat(detectAlias(QUERY), IS_U);
|
||||
assertThat(detectAlias(SIMPLE_QUERY), IS_U);
|
||||
assertThat(detectAlias(COUNT_QUERY), IS_U);
|
||||
assertThat(detectAlias(QUERY_WITH_AS), IS_U);
|
||||
assertThat(detectAlias("SELECT FROM USER U"), is("U"));
|
||||
assertThat(detectAlias("select u from User u"), IS_U);
|
||||
assertThat(detectAlias("select u from com.acme.User u"), IS_U);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsFullyQualifiedEntityNamesInQuery() {
|
||||
|
||||
assertThat(detectAlias(FQ_QUERY), IS_U);
|
||||
assertCountQuery(FQ_QUERY,
|
||||
"select count(u) from org.synyx.hades.domain.User$Foo_Bar u");
|
||||
}
|
||||
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
|
||||
assertThat(createCountQueryFor(originalQuery), is(countQuery));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link SimpleHadesQuery}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleJpaQueryUnitTests {
|
||||
|
||||
private JpaQueryMethod method;
|
||||
|
||||
@Mock
|
||||
private EntityManager em;
|
||||
@Mock
|
||||
private QueryExtractor extractor;
|
||||
@Mock
|
||||
private Query query;
|
||||
|
||||
|
||||
@Before
|
||||
@QueryHints(@QueryHint(name = "foo", value = "bar"))
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
when(em.createQuery(anyString())).thenReturn(query);
|
||||
|
||||
Method setUp =
|
||||
UserRepository.class.getMethod("findByLastname", String.class);
|
||||
method = new JpaQueryMethod(setUp, extractor, em);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void appliesHintsCorrectly() throws Exception {
|
||||
|
||||
SimpleJpaQuery hadesQuery = new SimpleJpaQuery(method, em, "foobar");
|
||||
hadesQuery.createQuery(em, new ParameterBinder(method.getParameters(),
|
||||
new Object[] { "gierke" }));
|
||||
|
||||
verify(query).setHint("foo", "bar");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void prefersDeclaredCountQueryOverCreatingOne() throws Exception {
|
||||
|
||||
method = mock(JpaQueryMethod.class);
|
||||
when(method.getCountQuery()).thenReturn("foo");
|
||||
when(em.createQuery("foo")).thenReturn(query);
|
||||
|
||||
SimpleJpaQuery hadesQuery =
|
||||
new SimpleJpaQuery(method, em, "select u from User u");
|
||||
|
||||
assertThat(hadesQuery.createCountQuery(em), is(query));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* DAO interface for {@code AuditableUser}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface AuditableUserRepository extends
|
||||
JpaRepository<AuditableUser, Long> {
|
||||
|
||||
/**
|
||||
* Returns all users with the given firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return all users with the given firstname.
|
||||
*/
|
||||
public List<AuditableUser> findByFirstname(final String firstname);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.Role;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Typing interface for {@code Role}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface RoleRepository extends JpaRepository<Role, Integer> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* DAO interface for {@code User}s. The declared methods will trigger named
|
||||
* queries as they start with {@code findBy}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<User, Integer>,
|
||||
UserRepositoryCustom {
|
||||
|
||||
/**
|
||||
* Retrieve users by their lastname. The finder
|
||||
* {@literal User.findByLastname} is declared in {@literal META-INF/orm.xml}
|
||||
* .
|
||||
*
|
||||
* @param lastname
|
||||
* @return all users with the given lastname
|
||||
*/
|
||||
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
|
||||
List<User> findByLastname(String lastname);
|
||||
|
||||
|
||||
/**
|
||||
* Redeclaration of {@link Repository#findById(java.io.Serializable)} to
|
||||
* change transaction configuration.
|
||||
*/
|
||||
@Transactional
|
||||
public User findById(Integer primaryKey);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve users by their email address. The finder
|
||||
* {@literal User.findByEmailAddress} is declared as annotation at
|
||||
* {@code User}.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @return the user with the given email address
|
||||
*/
|
||||
User findByEmailAddress(String emailAddress);
|
||||
|
||||
|
||||
@Query("select u from User u ")
|
||||
Page<User> findAllPaged(Pageable pageable);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves users by the given email and lastname. Acts as a dummy method
|
||||
* declaration to test finder query creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @return the user with the given email address and lastname
|
||||
*/
|
||||
User findByEmailAddressAndLastname(String emailAddress, String lastname);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves users by email address and lastname or firstname. Acts as a
|
||||
* dummy method declaration to test finder query creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @param username
|
||||
* @return the users with the given email address and lastname or the given
|
||||
* firstname
|
||||
*/
|
||||
List<User> findByEmailAddressAndLastnameOrFirstname(String emailAddress,
|
||||
String lastname, String username);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a user by its username using the query annotated to the method.
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.emailAddress = ?1")
|
||||
@Transactional(readOnly = true)
|
||||
User findByHadesQuery(String emailAddress);
|
||||
|
||||
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable}
|
||||
* parameter to be regarded on query execution.
|
||||
*
|
||||
* @param pageable
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
Page<User> findByFirstname(Pageable pageable, String firstname);
|
||||
|
||||
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable}
|
||||
* parameter to be regarded on query execution. Just returns the queried
|
||||
* {@link Page}'s contents.
|
||||
*
|
||||
* @param firstname
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstname(String firstname, Pageable pageable);
|
||||
|
||||
|
||||
/**
|
||||
* Manipulating query to set all {@link User}'s names to the given one.
|
||||
*
|
||||
* @param lastname
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update User u set u.lastname = ?1")
|
||||
void renameAllUsersTo(String lastname);
|
||||
|
||||
|
||||
@Query("select count(u) from User u where u.firstname = ?1")
|
||||
Long countWithFirstname(String firstname);
|
||||
|
||||
|
||||
/**
|
||||
* Method where parameters will be applied by name. Note that the order of
|
||||
* the parameters is then not crucial anymore.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstname(@Param("firstname") String foo,
|
||||
@Param("lastname") String bar);
|
||||
|
||||
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstnameUnannotated(String firstname,
|
||||
String lastname);
|
||||
|
||||
|
||||
/**
|
||||
* Method to check query creation and named parameter usage go well hand in
|
||||
* hand.
|
||||
*
|
||||
* @param lastname
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstnameOrLastname(@Param("lastname") String lastname,
|
||||
@Param("firstname") String firstname);
|
||||
|
||||
|
||||
List<User> findByLastnameLikeOrderByFirstnameDesc(String lastname);
|
||||
|
||||
|
||||
List<User> findByLastnameNotLike(String lastname);
|
||||
|
||||
|
||||
List<User> findByLastnameNot(String lastname);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
|
||||
|
||||
/**
|
||||
* Simple interface for custom methods on the DAO for {@code User}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface UserRepositoryCustom {
|
||||
|
||||
/**
|
||||
* Method actually triggering a finder but being overridden.
|
||||
*/
|
||||
void findByOverrridingMethod();
|
||||
|
||||
|
||||
/**
|
||||
* Some custom method to implement.
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
void someCustomMethod(User user);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
|
||||
|
||||
/**
|
||||
* Dummy implementation to allow check for invoking a custom implementation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UserRepositoryImpl implements UserRepositoryCustom {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.synyx.hades.dao.UserDao#someOtherMethod(org.synyx.hades.domain.User)
|
||||
*/
|
||||
public void someCustomMethod(User u) {
|
||||
|
||||
System.out.println("Some custom method was invoked!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.synyx.hades.dao.UserDaoCustom#findFooMethod()
|
||||
*/
|
||||
public void findByOverrridingMethod() {
|
||||
|
||||
System.out.println("A mthod overriding a finder was invoked!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.sample.AuditableUserRepository;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Assures the injected DAO instances are wired to the customly configured
|
||||
* {@link EntityManagerFactory}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:multiple-entity-manager-integration-context.xml")
|
||||
public class EntityManagerFactoryRefTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
AuditableUserRepository auditableUserDao;
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void useUserRepository() throws Exception {
|
||||
|
||||
userRepository.saveAndFlush(new User("firstname", "lastname",
|
||||
"foo@bar.de"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional("transactionManager-2")
|
||||
public void useAuditableUserDao() throws Exception {
|
||||
|
||||
auditableUserDao.saveAndFlush(new AuditableUser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.hibernate.ejb.HibernateEntityManager;
|
||||
import org.junit.Test;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.jpa.repository.config.AbstractRepositoryConfigTests;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Assures the injected DAO instances are wired to the customly configured
|
||||
* {@link EntityManagerFactory}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:multiple-entity-manager-context.xml")
|
||||
public class EntityManagerFactoryRefUnitTests extends
|
||||
AbstractRepositoryConfigTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("entityManagerFactory")
|
||||
EntityManagerFactory first;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("secondEntityManagerFactory")
|
||||
EntityManagerFactory second;
|
||||
|
||||
|
||||
@Test
|
||||
public void daosGetTheSecondEntityManagerFactoryInjected() throws Exception {
|
||||
|
||||
verify(first, never()).createEntityManager();
|
||||
verify(second, atLeastOnce()).createEntityManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple No-Op {@link PersistenceExceptionTranslator} to be configured in
|
||||
* the test case's config file as it is required.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class NoOpPersistenceExceptionTranslator implements
|
||||
PersistenceExceptionTranslator {
|
||||
|
||||
public DataAccessException translateExceptionIfPossible(
|
||||
RuntimeException ex) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} to configure the mock
|
||||
* {@link EntityManagerFactory} instances. {@code entityManagerFactory} is
|
||||
* configured to be never invoked, {@code secondEntityManagerFactory} is
|
||||
* configured to be invoked at least once.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class MockPreparingBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
|
||||
if ("secondEntityManagerFactory".equals(beanName)) {
|
||||
|
||||
EntityManagerFactory entityManagerFactory =
|
||||
(EntityManagerFactory) bean;
|
||||
EntityManager em = mock(HibernateEntityManager.class);
|
||||
when(entityManagerFactory.createEntityManager()).thenReturn(em);
|
||||
|
||||
EntityManagerFactoryInfo info = (EntityManagerFactoryInfo) bean;
|
||||
when(info.getEntityManagerInterface()).thenAnswer(
|
||||
new Answer<Class<?>>() {
|
||||
|
||||
public Class<?> answer(InvocationOnMock invocation)
|
||||
throws Throwable {
|
||||
|
||||
return HibernateEntityManager.class;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.repository.support.IdAware;
|
||||
import org.springframework.data.repository.support.IsNewAware;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for various implementations of {@link IsNewAware}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaAnnotationEntityInformationUnitTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullAsDomainClass() throws Exception {
|
||||
|
||||
new JpaAnnotationEntityInformation(null);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNonEntityClasses() throws Exception {
|
||||
|
||||
new JpaAnnotationEntityInformation(NotAnnotatedEntity.class);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsEntityWithMissingIdAnnotation() throws Exception {
|
||||
|
||||
new JpaAnnotationEntityInformation(EntityWithOutIdAnnotation.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsFieldAnnotatedIdCorrectly() throws Exception {
|
||||
|
||||
JpaAnnotationEntityInformation info =
|
||||
new JpaAnnotationEntityInformation(FieldAnnotatedEntity.class);
|
||||
|
||||
assertNewAndNoId(info, new FieldAnnotatedEntity(null));
|
||||
assertNotNewAndId(info, new FieldAnnotatedEntity(1L), 1L);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsEmbeddedIdFieldAnnotatedIdCorrectly() throws Exception {
|
||||
|
||||
JpaAnnotationEntityInformation info =
|
||||
new JpaAnnotationEntityInformation(
|
||||
EmbeddedIdFieldAnnotatedEntity.class);
|
||||
|
||||
assertNewAndNoId(info, new EmbeddedIdFieldAnnotatedEntity(null));
|
||||
assertNotNewAndId(info, new EmbeddedIdFieldAnnotatedEntity(1L), 1L);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsMethodAnnotatedIdCorrectly() throws Exception {
|
||||
|
||||
JpaAnnotationEntityInformation info =
|
||||
new JpaAnnotationEntityInformation(MethodAnnotatedEntity.class);
|
||||
|
||||
assertNewAndNoId(info, new MethodAnnotatedEntity());
|
||||
|
||||
MethodAnnotatedEntity entity = new MethodAnnotatedEntity();
|
||||
entity.id = 1L;
|
||||
assertNotNewAndId(info, entity, 1L);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsEmbeddedIdMethodAnnotatedIdCorrectly() throws Exception {
|
||||
|
||||
JpaAnnotationEntityInformation strategy =
|
||||
new JpaAnnotationEntityInformation(
|
||||
EmbeddedIdMethodAnnotatedEntity.class);
|
||||
|
||||
assertNewAndNoId(strategy, new EmbeddedIdMethodAnnotatedEntity());
|
||||
|
||||
EmbeddedIdMethodAnnotatedEntity entity =
|
||||
new EmbeddedIdMethodAnnotatedEntity();
|
||||
entity.id = 1L;
|
||||
assertNotNewAndId(strategy, entity, 1L);
|
||||
}
|
||||
|
||||
|
||||
private <T extends IdAware & IsNewAware> void assertNewAndNoId(T info,
|
||||
Object entity) {
|
||||
|
||||
assertThat(info.isNew(entity), is(true));
|
||||
assertThat(info.getId(entity), is(nullValue()));
|
||||
}
|
||||
|
||||
|
||||
private <T extends IdAware & IsNewAware> void assertNotNewAndId(T info,
|
||||
Object entity, Object id) {
|
||||
|
||||
assertThat(info.isNew(entity), is(false));
|
||||
assertThat(info.getId(entity), is(id));
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class FieldAnnotatedEntity {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
|
||||
public FieldAnnotatedEntity(Long id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class EmbeddedIdFieldAnnotatedEntity {
|
||||
|
||||
@EmbeddedId
|
||||
Long id;
|
||||
|
||||
|
||||
public EmbeddedIdFieldAnnotatedEntity(Long id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class MethodAnnotatedEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class EmbeddedIdMethodAnnotatedEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
|
||||
@EmbeddedId
|
||||
public Long getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
static class NotAnnotatedEntity {
|
||||
|
||||
@Id
|
||||
public Long id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class EntityWithOutIdAnnotation {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code GenericDaoFactoryBean}.
|
||||
* <p>
|
||||
* TODO: Check if test methods double the ones in
|
||||
* {@link JpaRepositoryFactoryUnitTests}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaRepositoryFactoryBeanUnitTests {
|
||||
|
||||
JpaRepositoryFactoryBean<SimpleSampleRepository> factory;
|
||||
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
|
||||
@Mock
|
||||
ListableBeanFactory beanFactory;
|
||||
@Mock
|
||||
PersistenceExceptionTranslator translator;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
Map<String, PersistenceExceptionTranslator> beans =
|
||||
new HashMap<String, PersistenceExceptionTranslator>();
|
||||
beans.put("foo", translator);
|
||||
when(
|
||||
beanFactory.getBeansOfType(
|
||||
eq(PersistenceExceptionTranslator.class), anyBoolean(),
|
||||
anyBoolean())).thenReturn(beans);
|
||||
|
||||
// Setup standard factory configuration
|
||||
factory =
|
||||
JpaRepositoryFactoryBean.create(
|
||||
SimpleSampleRepository.class, entityManager);
|
||||
factory.setEntityManager(entityManager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a
|
||||
* valid {@code UserDao}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
|
||||
factory.setBeanFactory(beanFactory);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
assertNotNull(factory.getObject());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void requiresListableBeanFactory() throws Exception {
|
||||
|
||||
factory.setBeanFactory(mock(BeanFactory.class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that the factory rejects calls to
|
||||
* {@code GenericDaoFactoryBean#setDaoInterface(Class)} with {@code null} or
|
||||
* any other parameter instance not implementing {@code GenericDao}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullDaoInterface() {
|
||||
|
||||
factory.setRepositoryInterface(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that the factory detects unset DAO class and interface in
|
||||
* {@code GenericDaoFactoryBean#afterPropertiesSet()}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsUnsetDaoInterface() throws Exception {
|
||||
|
||||
factory = new JpaRepositoryFactoryBean<SimpleSampleRepository>();
|
||||
factory.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the factory recognized configured DAO classes that contain
|
||||
* custom method but no custom implementation could be found. Furthremore
|
||||
* the exception has to contain the name of the DAO interface as for a large
|
||||
* DAO configuration it's hard to find out where this error occured.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void capturesMissingCustomImplementationAndProvidesInterfacename()
|
||||
throws Exception {
|
||||
|
||||
JpaRepositoryFactoryBean<SampleRepository> factory =
|
||||
|
||||
JpaRepositoryFactoryBean.create(SampleRepository.class,
|
||||
entityManager);
|
||||
|
||||
try {
|
||||
factory.afterPropertiesSet();
|
||||
fail("Expected IllegalArgumentException!");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage()
|
||||
.contains(SampleRepository.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private interface SimpleSampleRepository extends
|
||||
JpaRepository<User, Integer> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample interface to contain a custom method.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private interface SampleCustomDao {
|
||||
|
||||
void someSampleMethod();
|
||||
}
|
||||
|
||||
private interface SampleRepository extends
|
||||
JpaRepository<User, Integer>, SampleCustomDao {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.custom.CustomGenericJpaRepositoryFactory;
|
||||
import org.springframework.data.jpa.repository.custom.UserCustomExtendedRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code GenericDaoFactoryBean}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaRepositoryFactoryUnitTests {
|
||||
|
||||
JpaRepositoryFactory factory;
|
||||
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
// Setup standard factory configuration
|
||||
factory = new JpaRepositoryFactory(entityManager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a
|
||||
* valid {@code UserDao}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
|
||||
assertNotNull(factory.getRepository(SimpleSampleDao.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsCallingOfObjectMethods() {
|
||||
|
||||
SimpleSampleDao userDao = factory.getRepository(SimpleSampleDao.class);
|
||||
|
||||
userDao.hashCode();
|
||||
userDao.toString();
|
||||
userDao.equals(userDao);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the factory recognized configured DAO classes that contain
|
||||
* custom method but no custom implementation could be found. Furthremore
|
||||
* the exception has to contain the name of the DAO interface as for a large
|
||||
* DAO configuration it's hard to find out where this error occured.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void capturesMissingCustomImplementationAndProvidesInterfacename()
|
||||
throws Exception {
|
||||
|
||||
try {
|
||||
factory.getRepository(SampleDao.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains(SampleDao.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void handlesRuntimeExceptionsCorrectly() {
|
||||
|
||||
SampleDao dao =
|
||||
factory.getRepository(SampleDao.class,
|
||||
new SampleCustomDaoImpl());
|
||||
dao.throwingRuntimeException();
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void handlesCheckedExceptionsCorrectly() throws Exception {
|
||||
|
||||
SampleDao dao =
|
||||
factory.getRepository(SampleDao.class,
|
||||
new SampleCustomDaoImpl());
|
||||
dao.throwingCheckedException();
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void createsProxyWithCustomBaseClass() throws Exception {
|
||||
|
||||
JpaRepositoryFactory factory =
|
||||
new CustomGenericJpaRepositoryFactory(entityManager);
|
||||
UserCustomExtendedRepository dao =
|
||||
factory.getRepository(UserCustomExtendedRepository.class);
|
||||
|
||||
dao.customMethod(1);
|
||||
}
|
||||
|
||||
private interface SimpleSampleDao extends
|
||||
JpaRepository<User, Integer> {
|
||||
|
||||
@Transactional
|
||||
User readByPrimaryKey(Integer primaryKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample interface to contain a custom method.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface SampleCustomDao {
|
||||
|
||||
void throwingRuntimeException();
|
||||
|
||||
|
||||
void throwingCheckedException() throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the custom DAO interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class SampleCustomDaoImpl implements SampleCustomDao {
|
||||
|
||||
public void throwingRuntimeException() {
|
||||
|
||||
throw new IllegalArgumentException("You lose!");
|
||||
}
|
||||
|
||||
|
||||
public void throwingCheckedException() throws IOException {
|
||||
|
||||
throw new IOException("You lose!");
|
||||
}
|
||||
}
|
||||
|
||||
private interface SampleDao extends JpaRepository<User, Integer>,
|
||||
SampleCustomDao {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2008-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.jpa.domain.sample.SampleEntity;
|
||||
import org.springframework.data.jpa.domain.sample.SampleEntityPK;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for {@link GenericJpaDao}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration({ "classpath:infrastructure.xml" })
|
||||
@Transactional
|
||||
public class JpaRepositoryTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
JpaRepository<SampleEntity, SampleEntityPK> repository;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
repository =
|
||||
new JpaRepositoryFactory(em)
|
||||
.getRepository(SampleEntityRepository.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCrudOperationsForCompoundKeyEntity() throws Exception {
|
||||
|
||||
SampleEntity entity = new SampleEntity("foo", "bar");
|
||||
repository.saveAndFlush(entity);
|
||||
assertThat(repository.count(), is(1L));
|
||||
assertThat(repository.findById(new SampleEntityPK("foo", "bar")),
|
||||
is(entity));
|
||||
|
||||
repository.delete(Arrays.asList(entity));
|
||||
repository.flush();
|
||||
assertThat(repository.count(), is(0L));
|
||||
}
|
||||
|
||||
private static interface SampleEntityRepository extends
|
||||
JpaRepository<SampleEntity, SampleEntityPK> {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for transactional behaviour of DAO operations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration({ "classpath:config/namespace-autoconfig-context.xml",
|
||||
"classpath:tx-manager.xml" })
|
||||
public class TransactionalRepositoryTests extends
|
||||
AbstractJUnit4SpringContextTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository repository;
|
||||
|
||||
@Autowired
|
||||
DelegatingTransactionManager transactionManager;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
transactionManager.resetCount();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void simpleManipulatingOperation() throws Exception {
|
||||
|
||||
repository.saveAndFlush(new User("foo", "bar", "foo@bar.de"));
|
||||
assertThat(transactionManager.getTransactionRequests(), is(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void unannotatedFinder() throws Exception {
|
||||
|
||||
repository.findByEmailAddress("foo@bar.de");
|
||||
assertThat(transactionManager.getTransactionRequests(), is(0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void invokeTransactionalFinder() throws Exception {
|
||||
|
||||
repository.findByHadesQuery("foo@bar.de");
|
||||
assertThat(transactionManager.getTransactionRequests(), is(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void invokeRedeclaredMethod() throws Exception {
|
||||
|
||||
repository.findById(1);
|
||||
assertFalse(transactionManager.getDefinition().isReadOnly());
|
||||
}
|
||||
|
||||
public static class DelegatingTransactionManager implements
|
||||
PlatformTransactionManager {
|
||||
|
||||
private PlatformTransactionManager txManager;
|
||||
private int transactionRequests;
|
||||
private TransactionDefinition definition;
|
||||
|
||||
|
||||
public DelegatingTransactionManager(PlatformTransactionManager txManager) {
|
||||
|
||||
this.txManager = txManager;
|
||||
}
|
||||
|
||||
|
||||
public void commit(TransactionStatus status)
|
||||
throws TransactionException {
|
||||
|
||||
txManager.commit(status);
|
||||
}
|
||||
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition)
|
||||
throws TransactionException {
|
||||
|
||||
this.transactionRequests++;
|
||||
this.definition = definition;
|
||||
|
||||
return txManager.getTransaction(definition);
|
||||
}
|
||||
|
||||
|
||||
public int getTransactionRequests() {
|
||||
|
||||
return transactionRequests;
|
||||
}
|
||||
|
||||
|
||||
public TransactionDefinition getDefinition() {
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
|
||||
public void resetCount() {
|
||||
|
||||
this.transactionRequests = 0;
|
||||
this.definition = null;
|
||||
}
|
||||
|
||||
|
||||
public void rollback(TransactionStatus status)
|
||||
throws TransactionException {
|
||||
|
||||
txManager.rollback(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Test cases for ORM DAO implementations.</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.data.jpa.repository.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.repository.utils.JpaClassUtils.*;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaClassUtilsUnitTests {
|
||||
|
||||
@Test
|
||||
public void usesSimpleClassNameIfNoEntityNameGiven() throws Exception {
|
||||
|
||||
assertEquals("User", getEntityName(User.class));
|
||||
assertEquals("AnotherNamedUser", getEntityName(NamedUser.class));
|
||||
}
|
||||
|
||||
static class User {
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "AnotherNamedUser")
|
||||
static class NamedUser {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user