Added showcase for JDK 8's Optional support on repository methods.

Abbreviated JPA sample module folder names. Renamed the Java 8 auditing sample module to Java 8 module as it not only contains samples for auditing anymore.
This commit is contained in:
Oliver Gierke
2014-04-22 14:48:00 +02:00
parent dadaf374c3
commit 0ddb2ba0d6
74 changed files with 95 additions and 19 deletions

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.auditing;
import javax.persistence.Entity;
import org.springframework.data.domain.Auditable;
import org.springframework.data.jpa.domain.AbstractAuditable;
/**
* User domain class that uses auditing functionality of Spring Data that can either be aquired implementing
* {@link Auditable} or extend {@link AbstractAuditable}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Entity
public class AuditableUser extends AbstractAuditable<AuditableUser, Long> {
private static final long serialVersionUID = 1L;
private String username;
/**
* Set's the user's name.
*
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Returns the user's name.
*
* @return the username
*/
public String getUsername() {
return username;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.auditing;
import org.springframework.data.repository.CrudRepository;
/**
* @author Oliver Gierke
*/
public interface AuditableUserRepository extends CrudRepository<AuditableUser, Long> {
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2014 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 example.springdata.jpa.auditing;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
/**
* @author Oliver Gierke
*/
@Configuration
@EnableAutoConfiguration
@EnableJpaAuditing
class AuditingConfiguration {
/**
* We need to configure a {@link LocalContainerEntityManagerFactoryBean} manually here as Spring does <em>not</em>
* automatically add the {@code orm.xml} <em>if</em> a {@code persistence.xml} is located right beside it. This is
* necessary to get the {@link example.springdata.jpa.basics.BasicFactorySetup} sample working. However, in a {code
* persistence.xml}-less codebase you can rely on Spring Boot on setting the correct defaults.
*
* @return
*/
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.HSQL);
adapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPackagesToScan(getClass().getPackage().getName());
factoryBean.setMappingResources("META-INF/orm.xml");
factoryBean.setJpaVendorAdapter(adapter);
factoryBean.setDataSource(dataSource);
return factoryBean;
}
@Bean
AuditorAwareImpl auditorAware() {
return new AuditorAwareImpl();
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.auditing;
import org.springframework.data.domain.AuditorAware;
/**
* Dummy implementation of {@link AuditorAware}. It will return the configured {@link AuditableUser} as auditor on every
* call to {@link #getCurrentAuditor()}. Normally you would access the applications security subsystem to return the
* current user.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class AuditorAwareImpl implements AuditorAware<AuditableUser> {
private AuditableUser auditor;
/**
* @param auditor the auditor to set
*/
public void setAuditor(AuditableUser auditor) {
this.auditor = auditor;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.AuditorAware#getCurrentAuditor()
*/
public AuditableUser getCurrentAuditor() {
return auditor;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Package showing auditing support with Spring Data repositories.
*/
package example.springdata.jpa.auditing;

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.caching;
import java.util.Arrays;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Java config to use Spring Data JPA alongside the Spring caching support.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Configuration
@EnableCaching
@EnableAutoConfiguration
class CachingConfiguration {
@Bean
public CacheManager cacheManager() {
Cache cache = new ConcurrentMapCache("byUsername");
SimpleCacheManager manager = new SimpleCacheManager();
manager.setCaches(Arrays.asList(cache));
return manager;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.caching;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.repository.CrudRepository;
/**
* User repository using Spring's caching abstraction.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public interface CachingUserRepository extends CrudRepository<User, Long> {
@Override
@CacheEvict("byUsername")
<S extends User> S save(S entity);
@Cacheable("byUsername")
User findByUsername(String username);
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.caching;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQuery;
import org.springframework.data.jpa.domain.AbstractPersistable;
/**
* Sample user class.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Entity
@NamedQuery(name = "User.findByTheUsersName", query = "from User u where u.username = ?1")
public class User extends AbstractPersistable<Long> {
private static final long serialVersionUID = -2952735933715107252L;
@Column(unique = true) private String username;
private String firstname;
private String lastname;
public User() {
this(null);
}
/**
* Creates a new user instance.
*/
public User(Long id) {
this.setId(id);
}
/**
* Returns the username.
*
* @return
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the firstname
*/
public String getFirstname() {
return firstname;
}
/**
* @param firstname the firstname to set
*/
public void setFirstname(String firstname) {
this.firstname = firstname;
}
/**
* @return the lastname
*/
public String getLastname() {
return lastname;
}
/**
* @param lastname the lastname to set
*/
public void setLastname(String lastname) {
this.lastname = lastname;
}
}

View File

@@ -0,0 +1,5 @@
/**
* Sample for the integration of the Spring caching abstraction with Spring Data repositories.
*/
package example.springdata.jpa.caching;

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
/**
* Sample configuration to bootstrap Spring Data JPA through JavaConfig
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@Configuration
@EnableAutoConfiguration
class CustomRepositoryConfig {}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQuery;
import org.springframework.data.jpa.domain.AbstractPersistable;
/**
* Sample user class.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Entity
@NamedQuery(name = "User.findByTheUsersName", query = "from User u where u.username = ?1")
public class User extends AbstractPersistable<Long> {
private static final long serialVersionUID = -2952735933715107252L;
@Column(unique = true) private String username;
private String firstname;
private String lastname;
public User() {
this(null);
}
/**
* Creates a new user instance.
*/
public User(Long id) {
this.setId(id);
}
/**
* Returns the username.
*
* @return
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the firstname
*/
public String getFirstname() {
return firstname;
}
/**
* @param firstname the firstname to set
*/
public void setFirstname(String firstname) {
this.firstname = firstname;
}
/**
* @return the lastname
*/
public String getLastname() {
return lastname;
}
/**
* @param lastname the lastname to set
*/
public void setLastname(String lastname) {
this.lastname = lastname;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
/**
* Repository interface for {@link User} instances. Provides basic CRUD operations due to the extension of
* {@link JpaRepository}. Includes custom implemented functionality by extending {@link UserRepositoryCustom}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
/**
* Find the user with the given username. This method will be translated into a query using the
* {@link javax.persistence.NamedQuery} annotation at the {@link User} class.
*
* @param username
* @return
*/
User findByTheUsersName(String username);
/**
* Find all users with the given lastname. This method will be translated into a query by constructing it directly
* from the method name as there is no other query declared.
*
* @param lastname
* @return
*/
List<User> findByLastname(String lastname);
/**
* Returns all users with the given firstname. This method will be translated into a query using the one declared in
* the {@link Query} annotation declared one.
*
* @param firstname
* @return
*/
@Query("select u from User u where u.firstname = ?1")
List<User> findByFirstname(String firstname);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import java.util.List;
/**
* Interface for repository functionality that ought to be implemented manually.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
interface UserRepositoryCustom {
/**
* Custom repository operation.
*
* @return
*/
List<User> myCustomBatchOperation();
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
/**
* Implementation fo the custom repository functionality declared in {@link UserRepositoryCustom} based on JPA. To use
* this implementation in combination with Spring Data JPA you can either register it programatically:
*
* <pre>
* EntityManager em = ... // Obtain EntityManager
*
* UserRepositoryCustom custom = new UserRepositoryImpl();
* custom.setEntityManager(em);
*
* RepositoryFactorySupport factory = new JpaRepositoryFactory(em);
* UserRepository repository = factory.getRepository(UserRepository.class, custom);
* </pre>
*
* Using the Spring namespace the implementation will just get picked up due to the classpath scanning for
* implementations with the {@code Impl} postfix.
*
* <pre>
* &lt;jpa:repositories base-package=&quot;com.acme.repository&quot; /&gt;
* </pre>
*
* If you need to manually configure the custom instance see {@link UserRepositoryImplJdbc} for an example.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext private EntityManager em;
/**
* Configure the entity manager to be used.
*
* @param em the {@link EntityManager} to set.
*/
public void setEntityManager(EntityManager em) {
this.em = em;
}
/*
* (non-Javadoc)
* @see example.springdata.jpa.UserRepositoryCustom#myCustomBatchOperation()
*/
public List<User> myCustomBatchOperation() {
CriteriaQuery<User> criteriaQuery = em.getCriteriaBuilder().createQuery(User.class);
criteriaQuery.select(criteriaQuery.from(User.class));
return em.createQuery(criteriaQuery).getResultList();
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Component;
/**
* Class with the implementation of the custom repository code. Uses JDBC in this case. For basic programatic setup see
* {@link UserRepositoryImpl} for examples.
* <p>
* As you need to hand the instance a {@link javax.sql.DataSource} or
* {@link org.springframework.jdbc.core.simple.SimpleJdbcTemplate} you manually need to declare it as Spring bean:
*
* <pre>
* &lt;jpa:repository base-package=&quot;com.acme.repository&quot; /&gt;
*
* &lt;bean id=&quot;userRepositoryImpl&quot; class=&quot;...UserRepositoryJdbcImpl&quot;&gt;
* &lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&gt;
* &lt;/bean&gt;
* </pre>
*
* Using {@code userRepositoryImpl} will cause the repository instance get this bean injected for custom repository
* logic as the default postfix for custom DAO instances is {@code Impl}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Profile("jdbc")
@Component("userRepositoryImpl")
class UserRepositoryImplJdbc extends JdbcDaoSupport implements UserRepositoryCustom {
private static final String COMPLICATED_SQL = "SELECT * FROM User";
@Autowired
public UserRepositoryImplJdbc(DataSource dataSource) {
setDataSource(dataSource);
}
/*
* (non-Javadoc)
* @see example.springdata.jpa.UserRepositoryCustom#myCustomBatchOperation()
*/
public List<User> myCustomBatchOperation() {
return getJdbcTemplate().query(COMPLICATED_SQL, new UserRowMapper());
}
private static class UserRowMapper implements ParameterizedRowMapper<User> {
/*
* (non-Javadoc)
* @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int)
*/
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User(rs.getLong("id"));
user.setUsername(rs.getString("username"));
user.setLastname(rs.getString("lastname"));
user.setFirstname(rs.getString("firstname"));
return user;
}
}
}

View File

@@ -0,0 +1,5 @@
/**
* Package showing a repository interface to use basic query method execution functionality as well as <em>customized</em> repository functionality.
*/
package example.springdata.jpa.custom;

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2014 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 example.springdata.jpa.simple;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
/**
* @author Oliver Gierke
*/
@Configuration
@EnableAutoConfiguration
class SimpleConfiguration {}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.simple;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import com.google.common.base.Optional;
/**
* Simple repository interface for {@link User} instances. The interface is used to declare so called query methods,
* methods to retrieve single entities or collections of them.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public interface SimpleUserRepository extends CrudRepository<User, Long> {
/**
* Find the user with the given username. This method will be translated into a query using the
* {@link javax.persistence.NamedQuery} annotation at the {@link User} class.
*
* @param lastname
* @return
*/
User findByTheUsersName(String username);
Optional<User> findByUsername(String username);
/**
* Find all users with the given lastname. This method will be translated into a query by constructing it directly
* from the method name as there is no other query declared.
*
* @param lastname
* @return
*/
List<User> findByLastname(String lastname);
/**
* Returns all users with the given firstname. This method will be translated into a query using the one declared in
* the {@link Query} annotation declared one.
*
* @param firstname
* @return
*/
@Query("select u from User u where u.firstname = ?")
List<User> findByFirstname(String firstname);
/**
* Returns all users with the given name as first- or lastname. Makes use of the {@link Param} annotation to use named
* parameters in queries. This makes the query to method relation much more refactoring safe as the order of the
* method parameters is completely irrelevant.
*
* @param name
* @return
*/
@Query("select u from User u where u.firstname = :name or u.lastname = :name")
List<User> findByFirstnameOrLastname(@Param("name") String name);
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.simple;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQuery;
import org.springframework.data.jpa.domain.AbstractPersistable;
/**
* Sample user class.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Entity
@NamedQuery(name = "User.findByTheUsersName", query = "from User u where u.username = ?1")
public class User extends AbstractPersistable<Long> {
private static final long serialVersionUID = -2952735933715107252L;
@Column(unique = true) private String username;
private String firstname;
private String lastname;
public User() {
this(null);
}
/**
* Creates a new user instance.
*/
public User(Long id) {
this.setId(id);
}
/**
* Returns the username.
*
* @return
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the firstname
*/
public String getFirstname() {
return firstname;
}
/**
* @param firstname the firstname to set
*/
public void setFirstname(String firstname) {
this.firstname = firstname;
}
/**
* @return the lastname
*/
public String getLastname() {
return lastname;
}
/**
* @param lastname the lastname to set
*/
public void setLastname(String lastname) {
this.lastname = lastname;
}
}

View File

@@ -0,0 +1,5 @@
/**
* Package showing a simple repository interface to use basic query method execution functionality.
*/
package example.springdata.jpa.simple;

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd" version="2.0">
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2014 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 example.springdata.jpa.auditing;
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.jpa.domain.support.AuditingEntityListener;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;
import example.springdata.jpa.auditing.AuditableUser;
import example.springdata.jpa.auditing.AuditableUserRepository;
import example.springdata.jpa.auditing.AuditingConfiguration;
import example.springdata.jpa.auditing.AuditorAwareImpl;
/**
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = AuditingConfiguration.class)
public class AuditableUserSample {
@Autowired AuditableUserRepository repository;
@Autowired AuditorAwareImpl auditorAware;
@Autowired AuditingEntityListener listener;
@Test
public void auditEntityCreation() throws Exception {
assertThat(ReflectionTestUtils.getField(listener, "handler"), is(notNullValue()));
AuditableUser user = new AuditableUser();
user.setUsername("username");
auditorAware.setAuditor(user);
user = repository.save(user);
user = repository.save(user);
assertEquals(user, user.getCreatedBy());
assertEquals(user, user.getLastModifiedBy());
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.basics;
import static org.junit.Assert.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import example.springdata.jpa.simple.SimpleUserRepository;
import example.springdata.jpa.simple.User;
/**
* Test case showing how to use the basic {@link GenericDaoFactory}
*
* @author Oliver Gierke
*/
public class BasicFactorySetup {
private static final EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa.sample.plain");
private SimpleUserRepository userRepository;
private EntityManager em;
private User user;
/**
* Creates a {@link SimpleUserRepository} instance.
*
* @throws Exception
*/
@Before
public void setUp() {
em = factory.createEntityManager();
userRepository = new JpaRepositoryFactory(em).getRepository(SimpleUserRepository.class);
em.getTransaction().begin();
user = new User();
user.setUsername("username");
user.setFirstname("firstname");
user.setLastname("lastname");
user = userRepository.save(user);
}
/**
* Rollback transaction.
*/
@After
public void tearDown() {
em.getTransaction().rollback();
}
/**
* Showing invocation of finder method.
*/
@Test
public void executingFinders() {
assertEquals(user, userRepository.findByTheUsersName("username"));
assertEquals(user, userRepository.findByLastname("lastname").get(0));
assertEquals(user, userRepository.findByFirstname("firstname").get(0));
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Licenseimport static org.junit.Assert.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.jpa.example.domain.User;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.CrudRepository;
ess or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.basics;
import static org.junit.Assert.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.CrudRepository;
import example.springdata.jpa.simple.User;
/**
* This unit tests shows plain usage of {@link SimpleJpaRepository}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class BasicSample {
private CrudRepository<User, Long> userRepository;
private EntityManager em;
/**
* Sets up a {@link SimpleJpaRepository} instance.
*/
@Before
public void setUp() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa.sample.plain");
em = factory.createEntityManager();
userRepository = new SimpleJpaRepository<User, Long>(User.class, em);
em.getTransaction().begin();
}
@After
public void tearDown() {
em.getTransaction().rollback();
}
/**
* Tests saving users. Don't mimic transactionality shown here. It seriously lacks resource cleanup in case of an
* exception. Simplification serves descriptivness.
*/
@Test
public void savingUsers() {
User user = new User();
user.setUsername("username");
user = userRepository.save(user);
assertEquals(user, userRepository.findOne(user.getId()));
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
*
* @author Thomas Darimont
*/
package example.springdata.jpa.basics;

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.caching;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import example.springdata.jpa.caching.CachingConfiguration;
import example.springdata.jpa.caching.CachingUserRepository;
import example.springdata.jpa.caching.User;
/**
* Integration test to show how to use {@link Cacheable} with a Spring Data repository.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = CachingConfiguration.class)
public abstract class CachingRepositoryTests {
@Autowired CachingUserRepository repository;
@Autowired CacheManager cacheManager;
@Test
public void cachesValuesReturnedForQueryMethod() {
User dave = new User();
dave.setUsername("dmatthews");
dave = repository.save(dave);
User result = repository.findByUsername("dmatthews");
assertThat(result, is(dave));
// Verify entity cached
Cache cache = cacheManager.getCache("byUsername");
ValueWrapper wrapper = cache.get("dmatthews");
assertThat(wrapper.get(), is((Object) dave));
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.custom;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Intergration test showing the basic usage of {@link UserRepository}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = CustomRepositoryConfig.class)
// @ActiveProfiles("jdbc") // Uncomment @ActiveProfiles to enable the JDBC Implementation of the custom repository
public class UserRepositoryCustomizationTests {
@Autowired UserRepository repository;
/**
* Tests inserting a user and asserts it can be loaded again.
*/
@Test
public void testInsert() {
User user = new User();
user.setUsername("username");
user = repository.save(user);
assertEquals(user, repository.findOne(user.getId()));
}
@Test
public void saveAndFindByLastNameAndFindByUserName() {
User user = new User();
user.setUsername("foobar");
user.setLastname("lastname");
user = repository.save(user);
List<User> users = repository.findByLastname("lastname");
assertNotNull(users);
assertTrue(users.contains(user));
User reference = repository.findByTheUsersName("foobar");
assertEquals(user, reference);
}
/**
* Test invocation of custom method.
*/
@Test
public void testCustomMethod() {
User user = new User();
user.setUsername("username");
user = repository.save(user);
List<User> users = repository.myCustomBatchOperation();
assertNotNull(users);
assertTrue(users.contains(user));
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2013-2014 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 example.springdata.jpa.simple;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Intergration test showing the basic usage of {@link SimpleUserRepository}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = SimpleConfiguration.class)
public class SimpleUserRepositoryTests {
@Autowired SimpleUserRepository repository;
User user;
@Before
public void setUp() {
user = new User();
user.setUsername("foobar");
user.setFirstname("firstname");
user.setLastname("lastname");
}
@Test
public void findSavedUserById() {
user = repository.save(user);
assertThat(repository.findOne(user.getId()), is(user));
}
@Test
public void findSavedUserByLastname() throws Exception {
user = repository.save(user);
List<User> users = repository.findByLastname("lastname");
assertThat(users, is(notNullValue()));
assertThat(users.contains(user), is(true));
}
@Test
public void findByFirstnameOrLastname() throws Exception {
user = repository.save(user);
List<User> users = repository.findByFirstnameOrLastname("lastname");
assertThat(users.contains(user), is(true));
}
@Test
public void useGuavaOptionalInsteadOfNulls() {
assertThat(repository.findByUsername("foobar").isPresent(), is(false));
repository.save(user);
assertThat(repository.findByUsername("foobar").isPresent(), is(true));
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="jpa.sample.plain">
<class>example.springdata.jpa.simple.User</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:spring" />
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="error" />
<root level="error">
<appender-ref ref="console" />
</root>
</configuration>