diff --git a/java8-auditing/pom.xml b/java8-auditing/pom.xml new file mode 100644 index 0000000..e1fb3cf --- /dev/null +++ b/java8-auditing/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + + org.springframework.data.jpa.examples + spring-data-jpa-examples-parent + 1.1.0.RELEASE + + + java8-auditing + Spring Data JPA - Auditing on Java 8 and Spring 4 + + + 4.0.1.BUILD-SNAPSHOT + 1.5.0.BUILD-SNAPSHOT + + + + + + org.springframework + spring-aspects + + + + + + + + spring-libs-snapshot + http://repo.spring.io/libs-snapshot + + + + + \ No newline at end of file diff --git a/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/AbstractEntity.java b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/AbstractEntity.java new file mode 100644 index 0000000..33a1b0a --- /dev/null +++ b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/AbstractEntity.java @@ -0,0 +1,42 @@ +/* + * 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. + */ +package org.springframework.data.jpa.examples.java8; + +import java.time.ZonedDateTime; + +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; + +/** + * @author Oliver Gierke + */ +@MappedSuperclass +public class AbstractEntity { + + @Id @GeneratedValue Long id; + + @CreatedDate// + // @Type(type = "org.jadira.usertype.dateandtime.threetenbp.PersistentZonedDateTime")// + ZonedDateTime createdDate; + + @LastModifiedDate// + // @Type(type = "org.jadira.usertype.dateandtime.threetenbp.PersistentZonedDateTime")// + ZonedDateTime modifiedDate; +} diff --git a/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/Customer.java b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/Customer.java new file mode 100644 index 0000000..132c944 --- /dev/null +++ b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/Customer.java @@ -0,0 +1,33 @@ +/* + * 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. + */ +package org.springframework.data.jpa.examples.java8; + +import javax.persistence.Entity; + +/** + * @author Oliver Gierke + */ +@Entity +public class Customer extends AbstractEntity { + + String firstname, lastname; + + public Customer(String firstname, String lastname) { + + this.firstname = firstname; + this.lastname = lastname; + } +} diff --git a/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/CustomerRepository.java b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/CustomerRepository.java new file mode 100644 index 0000000..cf0207a --- /dev/null +++ b/java8-auditing/src/main/java/org/springframework/data/jpa/examples/java8/CustomerRepository.java @@ -0,0 +1,25 @@ +/* + * 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. + */ +package org.springframework.data.jpa.examples.java8; + +import org.springframework.data.repository.CrudRepository; + +/** + * @author Oliver Gierke + */ +public interface CustomerRepository extends CrudRepository { + +} diff --git a/java8-auditing/src/main/resources/META-INF/orm.xml b/java8-auditing/src/main/resources/META-INF/orm.xml new file mode 100644 index 0000000..da5ba62 --- /dev/null +++ b/java8-auditing/src/main/resources/META-INF/orm.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/java8-auditing/src/test/java/org/springframework/data/jpa/examples/java8/Java8AuditingIntegrationTests.java b/java8-auditing/src/test/java/org/springframework/data/jpa/examples/java8/Java8AuditingIntegrationTests.java new file mode 100644 index 0000000..9a80834 --- /dev/null +++ b/java8-auditing/src/test/java/org/springframework/data/jpa/examples/java8/Java8AuditingIntegrationTests.java @@ -0,0 +1,58 @@ +/* + * 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 org.springframework.data.jpa.examples.java8; + +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.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration test to show the usage of Java 8 date time APIs with Spring Data JPA auditing. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class Java8AuditingIntegrationTests { + + @Configuration + @EnableAutoConfiguration + @EnableJpaRepositories + @EnableJpaAuditing + static class Config { + + } + + @Autowired CustomerRepository repository; + + @Test + public void auditingSetsJdk8DateTimeTypes() { + + Customer customer = repository.save(new Customer("Dave", "Matthews")); + + assertThat(customer.createdDate, is(notNullValue())); + assertThat(customer.modifiedDate, is(notNullValue())); + } +} diff --git a/java8-auditing/src/test/resources/logback.xml b/java8-auditing/src/test/resources/logback.xml new file mode 100644 index 0000000..b48bf20 --- /dev/null +++ b/java8-auditing/src/test/resources/logback.xml @@ -0,0 +1,18 @@ + + + + + + %d %5p %40.40c:%4L - %m%n + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 01203af..e0b7654 100644 --- a/pom.xml +++ b/pom.xml @@ -4,37 +4,41 @@ org.springframework.data.jpa.examples spring-data-jpa-examples-parent - 1.0.0.BUILD-SNAPSHOT + 1.1.0.RELEASE pom + + org.springframework.boot + spring-boot-starter-parent + 1.0.0.RC1 + + Spring Data JPA sample projects Sample projects for Spring Data JPA http://www.springframework.org/spring-data - 2010 + 2011 spring-data-jpa-example spring-data-jpa-showcase + spring-data-jpa-interceptors + java8-auditing - gierke + ogierke Oliver Gierke - ogierke@vmware.com + ogierke@gopivotal.com http://www.olivergierke.de - 3.0.5.RELEASE - 2.0.0 - 4.8 - 3.5.6-Final - 1.5.8 - 1.6.8 - 1.5.2 + 4.0.0.RELEASE UTF-8 + 1.5.0.M1 + 4.3.0.Final @@ -42,107 +46,42 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3 - 1.6 - 1.6 - - - - com.springsource.bundlor - com.springsource.bundlor.maven - 1.0.0.RELEASE - - - bundlor - - bundlor - - process-classes - - - - true + 1.7 + 1.7 - - - org.springframework.data - spring-data-jpa - ${project.version} - - + - javax.persistence - com.springsource.javax.persistence - ${jpa.version} + org.springframework.boot + spring-boot-starter-data-jpa - + - junit - junit - ${junit.version} - test + org.springframework.boot + spring-boot-starter-test - - - log4j - log4j - 1.2.16 - test - - - org.springframework - spring-test - ${spring.version} - test - - - - org.hibernate - hibernate-entitymanager - ${hibernate.version} - runtime - - - org.slf4j - slf4j-log4j12 - ${slf4j.version} - runtime - - - - - org.hsqldb - com.springsource.org.hsqldb - 1.8.0.9 - runtime - - + joda-time joda-time - ${jodatime.version} - + - org.aspectj - aspectjweaver - ${aspectj.version} - runtime + org.hsqldb + hsqldb - jboss - JBoss repository - https://repository.jboss.org/nexus/content/repositories/releases + spring-milestones + http://repo.spring.io/libs-milestone diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..fff6c81 --- /dev/null +++ b/readme.md @@ -0,0 +1,8 @@ +# Spring Data JPA Examples + +This repository contains a variety of sample projects showing Spring Data JPA functionality. + +* `spring-data-jpa-example` - probably the project you want to have a look at first. Contains a variety of sample packages, showcasing the different levels at which you can use Spring Data JPA. Have a look at the `simple` package for the most basic setup. +* `java8-auditing` - example of how to use Spring Data JPA auditing with Java 8 date time types. +* `spring-data-jpa-showcase` - refactoring show case of how to improve a plain-JPA-based persistence layer by using Spring Data JPA (read: removing close to all of the implementation code). Follow the `demo.txt` file for detailed instructions. +* `spring-data-jpa-interceptors` - Example of how to enrich the repositories with AOP. diff --git a/spring-data-jpa-example/pom.xml b/spring-data-jpa-example/pom.xml index 5054169..184b43f 100644 --- a/spring-data-jpa-example/pom.xml +++ b/spring-data-jpa-example/pom.xml @@ -3,23 +3,22 @@ 4.0.0 spring-data-jpa-example - + org.springframework.data.jpa.examples spring-data-jpa-examples-parent - 1.0.0.BUILD-SNAPSHOT + 1.1.0.RELEASE ../pom.xml - Spring Data JPA sample + Spring Data JPA - Sample project Small sample project showing the usage of Sprign Data JPA. org.springframework - org.springframework.aspects - ${spring.version} + spring-aspects @@ -29,7 +28,6 @@ org.apache.maven.plugins maven-surefire-plugin - 2.4.3 **/*.java diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditableUser.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditableUser.java deleted file mode 100644 index 04e6617..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditableUser.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.springframework.data.jpa.example.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 - */ -@Entity -public class AuditableUser extends AbstractAuditable { - - 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; - } -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditorAwareImpl.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditorAwareImpl.java deleted file mode 100644 index 1a19dfb..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/auditing/AuditorAwareImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.springframework.data.jpa.example.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 - */ -public class AuditorAwareImpl implements AuditorAware { - - 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; - } - -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/domain/User.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/domain/User.java deleted file mode 100644 index ab2a5dd..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/domain/User.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.springframework.data.jpa.example.domain; - -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 - */ -@Entity -@NamedQuery(name = "User.findByTheUsersName", query = "from User u where u.username = ?") -public class User extends AbstractPersistable { - - 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; - } -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepository.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepository.java deleted file mode 100644 index 399c925..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -import java.util.List; - -import org.springframework.data.jpa.example.domain.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - - -/** - * 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 - */ -public interface UserRepository extends JpaRepository, 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 lastname - * @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 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 findByFirstname(String firstname); -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryCustom.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryCustom.java deleted file mode 100644 index 177ff20..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryCustom.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -import java.util.List; - -import org.springframework.data.jpa.example.domain.User; - - -/** - * Interface for repository functionality that ought to be implemented manually. - * - * @author Oliver Gierke - */ -interface UserRepositoryCustom { - - /** - * Custom repository operation. - * - * @return - */ - List myCustomBatchOperation(); -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryImpl.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryImpl.java deleted file mode 100644 index 2096ec7..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.criteria.CriteriaQuery; - -import org.springframework.data.jpa.example.domain.User; - - -/** - * 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: - * - *
- * EntityManager em = ... // Obtain EntityManager
- * 
- * UserRepositoryCustom custom = new UserRepositoryImpl();
- * custom.setEntityManager(em);
- * 
- * RepositoryFactorySupport factory = new JpaRepositoryFactory(em);
- * UserRepository repository = factory.getRepository(UserRepository.class, custom);
- * 
- * - * Using the Spring namespace the implementation will just get picked up due to - * the classpath scanning for implementations with the {@code Impl} postfix. - * - *
- * <jpa:repositories base-package="com.acme.repository" />
- * 
- * - * If you need to manually configure the custom instance see - * {@link UserRepositoryJdbcImpl} for an example. - * - * @author Oliver Gierke - */ -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 org.springframework.data.jpa.sample.repository.UserRepositoryCustom# - * myCustomBatchOperation() - */ - public List myCustomBatchOperation() { - - CriteriaQuery criteriaQuery = - em.getCriteriaBuilder().createQuery(User.class); - - return em.createQuery(criteriaQuery).getResultList(); - } - -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryJdbcImpl.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryJdbcImpl.java deleted file mode 100644 index 9644a20..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/UserRepositoryJdbcImpl.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.data.jpa.example.domain.User; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; -import org.springframework.jdbc.core.support.JdbcDaoSupport; - - -/** - * Class with the implementation of the custom repository code. Uses JDBC in - * this case. For basic programatic setup see {@link UserRepositoryImpl} for - * examples. - *

- * 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: - * - *

- * <jpa:repository base-package="com.acme.repository" />
- * 
- * <bean id="userRepositoryImpl" class="...UserRepositoryJdbcImpl">
- *   <property name="dataSource" ref="dataSource" />
- * </bean>
- * 
- * - * 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 - */ -class UserRepositoryJdbcImpl extends JdbcDaoSupport implements -UserRepositoryCustom { - - private static final String COMPLICATED_SQL = "SELECT * FROM User"; - - - /* - * (non-Javadoc) - * - * @see org.springframework.data.jpa.sample.repository.UserRepositoryCustom# - * myCustomBatchOperation() - */ - public List myCustomBatchOperation() { - - return getJdbcTemplate().query(COMPLICATED_SQL, new UserRowMapper()); - } - - private static class UserRowMapper implements ParameterizedRowMapper { - - /* - * (non-Javadoc) - * - * @see - * org.springframework.jdbc.core.simple.ParameterizedRowMapper#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; - } - } -} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUser.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUser.java new file mode 100644 index 0000000..4884c91 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUser.java @@ -0,0 +1,54 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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 { + + 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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserRepository.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserRepository.java new file mode 100644 index 0000000..c398452 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserRepository.java @@ -0,0 +1,25 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.auditing; + +import org.springframework.data.repository.CrudRepository; + +/** + * @author Oliver Gierke + */ +public interface AuditableUserRepository extends CrudRepository { + +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditingConfiguration.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditingConfiguration.java new file mode 100644 index 0000000..f95149e --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditingConfiguration.java @@ -0,0 +1,65 @@ +/* + * 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 org.springframework.data.jpa.example.repository.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 not + * automatically add the {@code orm.xml} if a {@code persistence.xml} is located right beside it. This is + * necessary to get the {@link org.springframework.data.jpa.example.repository.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(); + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditorAwareImpl.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditorAwareImpl.java new file mode 100644 index 0000000..2ee7fd6 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/AuditorAwareImpl.java @@ -0,0 +1,49 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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. + *

+ * TODO: change back to {@code AuditorAware} after SD Commons 1.7 RC1 as generic autowiring with Spring 4 + * will work with that version again. + * + * @author Oliver Gierke + * @author Thomas Darimont + */ +public class AuditorAwareImpl implements AuditorAware { + + 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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/package-info.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/package-info.java new file mode 100644 index 0000000..b046781 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/auditing/package-info.java @@ -0,0 +1,4 @@ +/** + * Package showing auditing support with Spring Data repositories. + */ +package org.springframework.data.jpa.example.repository.auditing; \ No newline at end of file diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingConfiguration.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingConfiguration.java new file mode 100644 index 0000000..556cb24 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingConfiguration.java @@ -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 org.springframework.data.jpa.example.repository.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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingUserRepository.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingUserRepository.java new file mode 100644 index 0000000..ed82aa2 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/CachingUserRepository.java @@ -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 org.springframework.data.jpa.example.repository.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 { + + @Override + @CacheEvict("byUsername") + S save(S entity); + + @Cacheable("byUsername") + User findByUsername(String username); +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/User.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/User.java new file mode 100644 index 0000000..da23c5f --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/User.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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 { + + 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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/package-info.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/package-info.java new file mode 100644 index 0000000..a5ea974 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/caching/package-info.java @@ -0,0 +1,5 @@ +/** + * Sample for the integration of the Spring caching abstraction with Spring Data repositories. + */ +package org.springframework.data.jpa.example.repository.caching; + diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/CustomRepositoryConfig.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/CustomRepositoryConfig.java new file mode 100644 index 0000000..89c5ccf --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/CustomRepositoryConfig.java @@ -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 org.springframework.data.jpa.example.repository.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 {} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/User.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/User.java new file mode 100644 index 0000000..7ef5f61 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/User.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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 { + + 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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepository.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepository.java new file mode 100644 index 0000000..e6e0d7a --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepository.java @@ -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 org.springframework.data.jpa.example.repository.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, 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 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 findByFirstname(String firstname); +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustom.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustom.java new file mode 100644 index 0000000..6ff76e7 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustom.java @@ -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 org.springframework.data.jpa.example.repository.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 myCustomBatchOperation(); +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImpl.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImpl.java new file mode 100644 index 0000000..dd75b81 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImpl.java @@ -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 org.springframework.data.jpa.example.repository.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: + * + *
+ * EntityManager em = ... // Obtain EntityManager
+ * 
+ * UserRepositoryCustom custom = new UserRepositoryImpl();
+ * custom.setEntityManager(em);
+ * 
+ * RepositoryFactorySupport factory = new JpaRepositoryFactory(em);
+ * UserRepository repository = factory.getRepository(UserRepository.class, custom);
+ * 
+ * + * Using the Spring namespace the implementation will just get picked up due to the classpath scanning for + * implementations with the {@code Impl} postfix. + * + *
+ * <jpa:repositories base-package="com.acme.repository" />
+ * 
+ * + * 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 org.springframework.data.jpa.example.repository.UserRepositoryCustom#myCustomBatchOperation() + */ + public List myCustomBatchOperation() { + + CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery(User.class); + criteriaQuery.select(criteriaQuery.from(User.class)); + return em.createQuery(criteriaQuery).getResultList(); + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImplJdbc.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImplJdbc.java new file mode 100644 index 0000000..750d09f --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryImplJdbc.java @@ -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 org.springframework.data.jpa.example.repository.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. + *

+ * 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: + * + *

+ * <jpa:repository base-package="com.acme.repository" />
+ * 
+ * <bean id="userRepositoryImpl" class="...UserRepositoryJdbcImpl">
+ *   <property name="dataSource" ref="dataSource" />
+ * </bean>
+ * 
+ * + * 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 org.springframework.data.jpa.example.repository.UserRepositoryCustom#myCustomBatchOperation() + */ + public List myCustomBatchOperation() { + return getJdbcTemplate().query(COMPLICATED_SQL, new UserRowMapper()); + } + + private static class UserRowMapper implements ParameterizedRowMapper { + + /* + * (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; + } + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/package-info.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/package-info.java new file mode 100644 index 0000000..2218bc3 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/package-info.java @@ -0,0 +1,5 @@ +/** + * Package showing a repository interface to use basic query method execution functionality as well as customized repository functionality. + */ +package org.springframework.data.jpa.example.repository.custom; + diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/package.html b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/package.html deleted file mode 100644 index 8d6a2fa..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - -

Package showing a repository interface to use basic finder method -execution functionality as well as customly implemented repository -functionality.

- - \ No newline at end of file diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleConfiguration.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleConfiguration.java new file mode 100644 index 0000000..4075257 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleConfiguration.java @@ -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 org.springframework.data.jpa.example.repository.simple; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; + +/** + * @author Oliver Gierke + */ +@Configuration +@EnableAutoConfiguration +class SimpleConfiguration {} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepository.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepository.java index 2170b5b..a01dbff 100644 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepository.java +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepository.java @@ -1,65 +1,71 @@ +/* + * 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 org.springframework.data.jpa.example.repository.simple; import java.util.List; -import org.springframework.data.jpa.example.domain.User; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; - /** - * 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. + * 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 JpaRepository { - - /** - * 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); - - - /** - * 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 findByLastname(String lastname); +public interface SimpleUserRepository extends CrudRepository { + /** + * 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); - /** - * 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 findByFirstname(String firstname); + /** + * 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 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 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 findByFirstnameOrLastname(@Param("name") String name); + /** + * 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 findByFirstnameOrLastname(@Param("name") String name); } diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/User.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/User.java new file mode 100644 index 0000000..ef7955e --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/User.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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 { + + 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; + } +} diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package-info.java b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package-info.java new file mode 100644 index 0000000..338e0e5 --- /dev/null +++ b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package-info.java @@ -0,0 +1,5 @@ +/** + * Package showing a simple repository interface to use basic query method execution functionality. + */ +package org.springframework.data.jpa.example.repository.simple; + diff --git a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package.html b/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package.html deleted file mode 100644 index d4ab49b..0000000 --- a/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -

Package showing a simple repository interface to use basic finder method execution functionality.

- - \ No newline at end of file diff --git a/spring-data-jpa-example/src/main/resources/META-INF/spring/osgi-context.xml b/spring-data-jpa-example/src/main/resources/META-INF/spring/osgi-context.xml deleted file mode 100644 index 18e91d7..0000000 --- a/spring-data-jpa-example/src/main/resources/META-INF/spring/osgi-context.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/spring-data-jpa-example/src/main/resources/auditing-context.xml b/spring-data-jpa-example/src/main/resources/auditing-context.xml deleted file mode 100644 index eccc8b9..0000000 --- a/spring-data-jpa-example/src/main/resources/auditing-context.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - diff --git a/spring-data-jpa-example/src/main/resources/infrastructure.xml b/spring-data-jpa-example/src/main/resources/infrastructure.xml deleted file mode 100644 index 4735da8..0000000 --- a/spring-data-jpa-example/src/main/resources/infrastructure.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-data-jpa-example/src/main/resources/log4j.properties b/spring-data-jpa-example/src/main/resources/log4j.properties deleted file mode 100644 index c96ca4c..0000000 --- a/spring-data-jpa-example/src/main/resources/log4j.properties +++ /dev/null @@ -1,12 +0,0 @@ -# Direct log messages to stdout -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %50.50c:%4L - %m%n - -# Root logger option -log4j.rootLogger=WARN, stdout - -# Detailed log levels -log4j.logger.org.springframework.data=DEBUG -#log4j.logger.org.springframework.jdbc=DEBUG \ No newline at end of file diff --git a/spring-data-jpa-example/src/main/resources/repository-context.xml b/spring-data-jpa-example/src/main/resources/repository-context.xml deleted file mode 100644 index 56efa4d..0000000 --- a/spring-data-jpa-example/src/main/resources/repository-context.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/spring-data-jpa-example/src/main/resources/simple-repository-context.xml b/spring-data-jpa-example/src/main/resources/simple-repository-context.xml deleted file mode 100644 index 2d7ad98..0000000 --- a/spring-data-jpa-example/src/main/resources/simple-repository-context.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/AuditableUserSample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/AuditableUserSample.java deleted file mode 100644 index 1e77417..0000000 --- a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/AuditableUserSample.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.springframework.data.jpa.example.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.data.jpa.example.auditing.AuditableUser; -import org.springframework.data.jpa.example.auditing.AuditorAwareImpl; -import org.springframework.data.repository.Repository; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - - -/** - * @author Oliver Gierke - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "classpath:auditing-context.xml" }) -@Transactional -public class AuditableUserSample { - - @Autowired - private Repository repository; - - @Autowired - private AuditorAwareImpl auditorAware; - - - @Test - public void testname() throws Exception { - - 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()); - } -} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicFactorySetup.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicFactorySetup.java deleted file mode 100644 index 9fefb72..0000000 --- a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicFactorySetup.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -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.example.domain.User; -import org.springframework.data.jpa.example.repository.simple.SimpleUserRepository; -import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; - - -/** - * 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)); - } -} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicSample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicSample.java deleted file mode 100644 index 181df7c..0000000 --- a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/BasicSample.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -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.example.domain.User; -import org.springframework.data.jpa.repository.support.SimpleJpaRepository; -import org.springframework.data.repository.Repository; - - -/** - * This unit tests shows plain usage of {@link SimpleJpaRepository}. - * - * @author Oliver Gierke - */ -public class BasicSample { - - private Repository 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 = SimpleJpaRepository.create(em, User.class); - - 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.findById(user.getId())); - } -} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/SimpleUserRepositorySample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/SimpleUserRepositorySample.java deleted file mode 100644 index 5d39c40..0000000 --- a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/SimpleUserRepositorySample.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -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.jpa.example.domain.User; -import org.springframework.data.jpa.example.repository.simple.SimpleUserRepository; -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 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "classpath:simple-repository-context.xml") -@Transactional -public class SimpleUserRepositorySample { - - @Autowired - SimpleUserRepository repository; - User user; - - - @Before - public void setUp() { - - user = new User(); - user.setUsername("foobar"); - user.setFirstname("firstname"); - user.setLastname("lastname"); - } - - - /** - * Tests inserting a user and asserts it can be loaded again. - */ - @Test - public void testInsert() { - - user = repository.save(user); - - assertEquals(user, repository.findById(user.getId())); - } - - - @Test - public void foo() throws Exception { - - user = repository.save(user); - - List users = repository.findByLastname("lastname"); - - assertNotNull(users); - assertTrue(users.contains(user)); - } - - - @Test - public void testname() throws Exception { - - user = repository.save(user); - - List users = repository.findByFirstnameOrLastname("lastname"); - - assertTrue(users.contains(user)); - } -} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/UserRepositorySample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/UserRepositorySample.java deleted file mode 100644 index d7ad01c..0000000 --- a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/UserRepositorySample.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.springframework.data.jpa.example.repository; - -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.data.jpa.example.domain.User; -import org.springframework.data.jpa.example.repository.UserRepository; -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 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "classpath:repository-context.xml") -@Transactional -public class UserRepositorySample { - - @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.findById(user.getId())); - } - - - @Test - public void foo() { - - User user = new User(); - user.setUsername("foobar"); - user.setLastname("lastname"); - - user = repository.save(user); - - List 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 users = repository.myCustomBatchOperation(); - - assertNotNull(users); - assertTrue(users.contains(user)); - } -} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserSample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserSample.java new file mode 100644 index 0000000..8c5e4ed --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/auditing/AuditableUserSample.java @@ -0,0 +1,59 @@ +/* + * 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 org.springframework.data.jpa.example.repository.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; + +/** + * @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()); + } +} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicFactorySetup.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicFactorySetup.java new file mode 100644 index 0000000..fab9f93 --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicFactorySetup.java @@ -0,0 +1,87 @@ +/* + * 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 org.springframework.data.jpa.example.repository.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.example.repository.simple.SimpleUserRepository; +import org.springframework.data.jpa.example.repository.simple.User; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; + +/** + * 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)); + } +} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicSample.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicSample.java new file mode 100644 index 0000000..74d7454 --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/BasicSample.java @@ -0,0 +1,79 @@ +/* + * 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 org.springframework.data.jpa.example.repository.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.example.repository.simple.User; +import org.springframework.data.jpa.repository.support.SimpleJpaRepository; +import org.springframework.data.repository.CrudRepository; + +/** + * This unit tests shows plain usage of {@link SimpleJpaRepository}. + * + * @author Oliver Gierke + * @author Thomas Darimont + */ +public class BasicSample { + + private CrudRepository 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.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())); + } +} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/package-info.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/package-info.java new file mode 100644 index 0000000..e3b82d7 --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/basics/package-info.java @@ -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 org.springframework.data.jpa.example.repository.basics; \ No newline at end of file diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/caching/CachingRepositoryTests.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/caching/CachingRepositoryTests.java new file mode 100644 index 0000000..8684f8a --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/caching/CachingRepositoryTests.java @@ -0,0 +1,62 @@ +/* + * 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 org.springframework.data.jpa.example.repository.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; + +/** + * 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)); + } +} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustomizationTests.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustomizationTests.java new file mode 100644 index 0000000..a5c2abe --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/custom/UserRepositoryCustomizationTests.java @@ -0,0 +1,91 @@ +/* + * 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. + */ +package org.springframework.data.jpa.example.repository.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 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 users = repository.myCustomBatchOperation(); + + assertNotNull(users); + assertTrue(users.contains(user)); + } +} diff --git a/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepositoryTests.java b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepositoryTests.java new file mode 100644 index 0000000..e9e7f3d --- /dev/null +++ b/spring-data-jpa-example/src/test/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepositoryTests.java @@ -0,0 +1,80 @@ +/* + * 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 org.springframework.data.jpa.example.repository.simple; + +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); + + assertEquals(user, repository.findOne(user.getId())); + } + + @Test + public void findSavedUserByLastname() throws Exception { + + user = repository.save(user); + + List users = repository.findByLastname("lastname"); + + assertNotNull(users); + assertTrue(users.contains(user)); + } + + @Test + public void findByFirstnameOrLastname() throws Exception { + + user = repository.save(user); + + List users = repository.findByFirstnameOrLastname("lastname"); + + assertTrue(users.contains(user)); + } +} diff --git a/spring-data-jpa-example/src/main/resources/META-INF/persistence.xml b/spring-data-jpa-example/src/test/resources/META-INF/persistence.xml similarity index 86% rename from spring-data-jpa-example/src/main/resources/META-INF/persistence.xml rename to spring-data-jpa-example/src/test/resources/META-INF/persistence.xml index c623c70..7f39b49 100644 --- a/spring-data-jpa-example/src/main/resources/META-INF/persistence.xml +++ b/spring-data-jpa-example/src/test/resources/META-INF/persistence.xml @@ -1,7 +1,8 @@ - - + + + org.springframework.data.jpa.example.repository.simple.User @@ -11,4 +12,5 @@ + diff --git a/spring-data-jpa-example/src/test/resources/logback.xml b/spring-data-jpa-example/src/test/resources/logback.xml new file mode 100644 index 0000000..40a8f33 --- /dev/null +++ b/spring-data-jpa-example/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + %d %5p %40.40c:%4L - %m%n + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-jpa-example/template.mf b/spring-data-jpa-example/template.mf deleted file mode 100644 index 5398885..0000000 --- a/spring-data-jpa-example/template.mf +++ /dev/null @@ -1,18 +0,0 @@ -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.springframework.data.jpa.example -Bundle-Name: ${project.name} -Bundle-Vendor: SpringSource -Bundle-Version: ${project.version} -Bundle-RequiredExecutionEnvironment: J2SE-1.6 -Import-Package: - javax.sql;version="0.0.0", - org.hsqldb;version="[1.8.0,1.9.0)" -Export-Template: - org.springframework.data.jpa.example.*;version="${project.version}" -Import-Template: - javax.persistence.*;version="${jpa.version:[=.=.=,+1.0.0)}", - org.springframework.*;version="${spring.version:[=.=.=.=,+1.0.0)}", - org.springframework.data.*;version="${project.version:[=.=.=.=,+1.0.0)}" -Import-Library: - org.springframework.spring;version="${spring.version:[=.=.=.=,+1.0.0)}", - org.hibernate.ejb;version="[3.5.6,4.0.0]" diff --git a/spring-data-jpa-interceptors/pom.xml b/spring-data-jpa-interceptors/pom.xml new file mode 100644 index 0000000..4fcb44c --- /dev/null +++ b/spring-data-jpa-interceptors/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + org.springframework.data.jpa.examples + spring-data-jpa-examples-parent + 1.1.0.RELEASE + ../pom.xml + + + spring-data-jpa-interceptors + Spring Data JPA - Interceptor sample + + diff --git a/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/ApplicationConfiguration.java b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/ApplicationConfiguration.java new file mode 100644 index 0000000..dd0d8aa --- /dev/null +++ b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/ApplicationConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-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 org.spring.data.jpa.sample.interceptors; + +import org.springframework.aop.Advisor; +import org.springframework.aop.aspectj.AspectJExpressionPointcut; +import org.springframework.aop.interceptor.CustomizableTraceInterceptor; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +@Configuration +@EnableAspectJAutoProxy +@EnableAutoConfiguration +public class ApplicationConfiguration { + + @Bean + public CustomizableTraceInterceptor interceptor() { + + CustomizableTraceInterceptor interceptor = new CustomizableTraceInterceptor(); + interceptor.setEnterMessage("Entering $[methodName]($[arguments])."); + interceptor.setExitMessage("Leaving $[methodName](..) with return value $[returnValue], took $[invocationTime]ms."); + + return interceptor; + } + + @Bean + public Advisor traceAdvisor() { + + AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); + pointcut.setExpression("execution(public * org.springframework.data.repository.Repository+.*(..))"); + + return new DefaultPointcutAdvisor(pointcut, interceptor()); + } +} diff --git a/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/Customer.java b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/Customer.java new file mode 100644 index 0000000..ac02635 --- /dev/null +++ b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/Customer.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012 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.spring.data.jpa.sample.interceptors; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Customer { + + @Id + @GeneratedValue + Long id; + + String firstname; + String lastname; + +} diff --git a/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/CustomerRepository.java b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/CustomerRepository.java new file mode 100644 index 0000000..1a2a788 --- /dev/null +++ b/spring-data-jpa-interceptors/src/main/java/org/spring/data/jpa/sample/interceptors/CustomerRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright 2012 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.spring.data.jpa.sample.interceptors; + +import org.springframework.data.repository.CrudRepository; + +public interface CustomerRepository extends CrudRepository { + +} diff --git a/spring-data-jpa-interceptors/src/test/java/org/spring/data/jpa/sample/interceptors/InterceptorIntegrationTest.java b/spring-data-jpa-interceptors/src/test/java/org/spring/data/jpa/sample/interceptors/InterceptorIntegrationTest.java new file mode 100644 index 0000000..6bfb237 --- /dev/null +++ b/spring-data-jpa-interceptors/src/test/java/org/spring/data/jpa/sample/interceptors/InterceptorIntegrationTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012 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.spring.data.jpa.sample.interceptors; + +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationConfiguration.class) +public class InterceptorIntegrationTest { + + @Autowired + CustomerRepository repository; + + @Test + public void foo() { + + Customer customer = new Customer(); + customer.firstname = "Dave"; + customer.lastname = "Matthews"; + + repository.save(customer); + } +} diff --git a/spring-data-jpa-interceptors/src/test/resources/logback.xml b/spring-data-jpa-interceptors/src/test/resources/logback.xml new file mode 100644 index 0000000..fd48d21 --- /dev/null +++ b/spring-data-jpa-interceptors/src/test/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + + %d %5p %40.40c:%4L - %m%n + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-jpa-showcase/demo.txt b/spring-data-jpa-showcase/demo.txt index 2e77e28..25607e2 100644 --- a/spring-data-jpa-showcase/demo.txt +++ b/spring-data-jpa-showcase/demo.txt @@ -8,31 +8,38 @@ 2. Issues --------- - Generics, simple queries, pagination (no metadata), is new?, arbitrary queries -- Approach: step by step refactoring -> introduce Hades +- Approach: step by step refactoring -> introduce Spring Data JPA -3. CustomerRepository ---------------------- -- add dependency to CustomerServiceImpl -- replace findById, findAll, save -- run test +5. AccountRepository +-------------------- +- replace save(…) +- findByCustomer -> show log -> method created from method name +- explain proxy mechanism, method signature possibilities (@Param, return types) 4. Explain general proxy mechanism, SimpleJpaRepository ------------------------------------------------- -- show GenericDao interface +- show JpaRepository interface - findAll(Pageable pageble) -5. AccountRepository --------------------- -- replace saven(…) -- findByCustomer -> show log -> method created from method name -- explain proxy mechanism, methods signature possibilities (@Param, return types, Pageable, Sort) -- -> replace findByLastname(Pageable pageable) in CustomerService +3. CustomerRepository +--------------------- +- add dependency to CustomerServiceImpl +- replace findById, findAll, save +- run test +- explain extended method signature possibilities (Pageable, Sort) +- replace findByLastname(Pageable pageable) in CustomerService 6. First summary ---------------- - implementation got obsolete - switch to after package --- alter packages to .after, remove component scan element + +7. Querydsl / Specifications +---------------------------- +- Introduce Querydsl +- Show Maven setup +- Show predicates +- Integrate test case 7. Custom implementation ------------------------ @@ -41,7 +48,7 @@ - copy test case - explain implementation class lookup -8. JDBC implementation +8. JDBC implementation (optional) ----------------------- - copy implementation -> configuration necessary - copy XML diff --git a/spring-data-jpa-showcase/pom.xml b/spring-data-jpa-showcase/pom.xml index 49c3e6e..8ffca35 100644 --- a/spring-data-jpa-showcase/pom.xml +++ b/spring-data-jpa-showcase/pom.xml @@ -1,64 +1,132 @@ - 4.0.0 - - spring-data-jpa-showcase - - - org.springframework.data.jpa.examples + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + spring-data-jpa-showcase + + + org.springframework.data.jpa.examples spring-data-jpa-examples-parent - 1.0.0.BUILD-SNAPSHOT + 1.1.0.RELEASE ../pom.xml - - - Spring Data JPA showcase - Sample project showing how Spring Data JPA eases implementing repositories over a plain JPA/Spring approach + + + Spring Data JPA - Refactoring showcase + Sample project showing how Spring Data JPA eases implementing repositories over a plain JPA/Spring approach + + + 3.3.0 + + + + + + + src/main/resources + + + src/snippets/resources + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${basedir}/src/snippets/java + + + + + add-test-source + generate-sources + + add-test-source + + + + ${basedir}/src/test-snippets/java + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/snippets/**/*.java + + + + + + + + + querydsl + + true + + + + + com.mysema.querydsl + querydsl-jpa + ${querydsl.version} + + + + + + + querydsl + QueryDsl + http://source.mysema.com/maven2/releases + + - - - - - src/main/resources - - - src/snippets/resources - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.5 - - - add-source - generate-sources - - add-source - - - - ${basedir}/src/snippets/java - - - - - add-test-source - generate-sources - - add-test-source - - - - ${basedir}/src/test-snippets/java - - - - - - - + + + + com.mysema.maven + apt-maven-plugin + 1.1.1 + + + com.mysema.querydsl + querydsl-apt + ${querydsl.version} + + + + + generate-sources + + process + + + target/generated-sources/queries + com.mysema.query.apt.jpa.JPAAnnotationProcessor + + + + + + + + \ No newline at end of file diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/AccountRepository.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/AccountRepository.java index f5a114d..3d40aa7 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/AccountRepository.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/AccountRepository.java @@ -2,23 +2,22 @@ import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; - +import org.springframework.data.repository.CrudRepository; /** * Repository to manage {@link Account} instances. * * @author Oliver Gierke */ -public interface AccountRepository extends JpaRepository { +public interface AccountRepository extends CrudRepository { - /** - * Returns all accounts belonging to the given {@link Customer}. - * - * @param customer - * @return - */ - List findByCustomer(Customer customer); + /** + * Returns all accounts belonging to the given {@link Customer}. + * + * @param customer + * @return + */ + List findByCustomer(Customer customer); } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/CustomerRepository.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/CustomerRepository.java index e36065f..9bd4e71 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/CustomerRepository.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/after/CustomerRepository.java @@ -1,35 +1,24 @@ package org.springframework.data.jpa.showcase.after; -import java.util.List; - import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.showcase.core.Customer; - +import org.springframework.data.repository.CrudRepository; /** * Repository to manage {@link Customer} instances. * * @author Oliver Gierke */ -public interface CustomerRepository extends JpaRepository { - - /** - * Returns all {@link Customer}s with the given lastname. - * - * @param lastname - * @return - */ - List findByLastname(String lastname); - +public interface CustomerRepository extends CrudRepository, JpaSpecificationExecutor { - /** - * Returns a page of {@link Customer}s with the given lastname. - * - * @param lastname - * @param pageable - * @return - */ - Page findByLastname(String lastname, Pageable pageable); + /** + * Returns a page of {@link Customer}s with the given lastname. + * + * @param lastname + * @param pageable + * @return + */ + Page findByLastname(String lastname, Pageable pageable); } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountService.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountService.java index 32f348d..a5c4a09 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountService.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountService.java @@ -5,7 +5,6 @@ import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; - /** * Service interface for {@link Account}s. * @@ -13,20 +12,19 @@ */ public interface AccountService { - /** - * Saves the given {@link Account}. - * - * @param account - * @return - */ - Account save(Account account); - + /** + * Saves the given {@link Account}. + * + * @param account + * @return + */ + Account save(Account account); - /** - * Returns all {@link Account}s of the given {@link Customer}. - * - * @param customer - * @return - */ - List findByCustomer(Customer customer); + /** + * Returns all {@link Account}s of the given {@link Customer}. + * + * @param customer + * @return + */ + List findByCustomer(Customer customer); } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountServiceImpl.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountServiceImpl.java index 1efcca2..728acbc 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountServiceImpl.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/AccountServiceImpl.java @@ -4,12 +4,12 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; -import javax.persistence.Query; +import javax.persistence.TypedQuery; import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; import org.springframework.stereotype.Repository; - +import org.springframework.transaction.annotation.Transactional; /** * Plain JPA implementation of {@link AccountService}. @@ -17,45 +17,38 @@ * @author Oliver Gierke */ @Repository +@Transactional(readOnly = true) class AccountServiceImpl implements AccountService { - @PersistenceContext - private EntityManager em; - - - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.before.AccountRepository#save(org.geecon.hades.before - * .Account) - */ - @Override - public Account save(Account account) { - - if (account.getId() == null) { - em.persist(account); - return account; - } else { - return em.merge(account); - } - } - - - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.before.AccountRepository#findByCustomer(org.geecon.hades - * .before.Customer) - */ - @Override - @SuppressWarnings("unchecked") - public List findByCustomer(Customer customer) { - - Query query = em.createQuery("from Account a where a.customer = ?"); - query.setParameter(1, customer); - - return query.getResultList(); - } + @PersistenceContext + private EntityManager em; + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.AccountService#save(org.springframework.data.jpa.showcase.core.Account) + */ + @Override + @Transactional + public Account save(Account account) { + + if (account.getId() == null) { + em.persist(account); + return account; + } else { + return em.merge(account); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.AccountService#findByCustomer(org.springframework.data.jpa.showcase.core.Customer) + */ + @Override + public List findByCustomer(Customer customer) { + + TypedQuery query = em.createQuery("select a from Account a where a.customer = ?1", Account.class); + query.setParameter(1, customer); + + return query.getResultList(); + } } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerService.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerService.java index a3cc9c9..9641387 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerService.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerService.java @@ -4,7 +4,6 @@ import org.springframework.data.jpa.showcase.core.Customer; - /** * Service interface for {@link Customer}s. * @@ -12,52 +11,46 @@ */ public interface CustomerService { - /** - * Returns the {@link Customer} with the given id or {@literal null} if no - * {@link Customer} with the given id was found. - * - * @param id - * @return - */ - Customer findById(Long id); - - - /** - * Saves the given {@link Customer}. - * - * @param customer - * @return - */ - Customer save(Customer customer); - - - /** - * Returns all customers. - * - * @return - */ - List findAll(); - - - /** - * Returns the page of {@link Customer}s with the given index of the given - * size. - * - * @param page - * @param pageSize - * @return - */ - List findAll(int page, int pageSize); - - - /** - * Returns the page of {@link Customer}s with the given lastname and the - * given page index and page size. - * - * @param lastname - * @param page - * @param pageSize - * @return - */ - List findByLastname(String lastname, int page, int pageSize); + /** + * Returns the {@link Customer} with the given id or {@literal null} if no {@link Customer} with the given id was + * found. + * + * @param id + * @return + */ + Customer findById(Long id); + + /** + * Saves the given {@link Customer}. + * + * @param customer + * @return + */ + Customer save(Customer customer); + + /** + * Returns all customers. + * + * @return + */ + List findAll(); + + /** + * Returns the page of {@link Customer}s with the given index of the given size. + * + * @param page + * @param pageSize + * @return + */ + List findAll(int page, int pageSize); + + /** + * Returns the page of {@link Customer}s with the given lastname and the given page index and page size. + * + * @param lastname + * @param page + * @param pageSize + * @return + */ + List findByLastname(String lastname, int page, int pageSize); } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerServiceImpl.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerServiceImpl.java index b87fee8..074e767 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerServiceImpl.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/before/CustomerServiceImpl.java @@ -4,11 +4,11 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; -import javax.persistence.Query; +import javax.persistence.TypedQuery; import org.springframework.data.jpa.showcase.core.Customer; import org.springframework.stereotype.Repository; - +import org.springframework.transaction.annotation.Transactional; /** * Plain JPA implementation of {@link CustomerService}. @@ -16,92 +16,75 @@ * @author Oliver Gierke */ @Repository +@Transactional(readOnly = true) public class CustomerServiceImpl implements CustomerService { - @PersistenceContext - private EntityManager em; - - - /* - * (non-Javadoc) - * - * @see org.geecon.hades.before.CustomerRepository#findById(java.lang.Long) - */ - @Override - public Customer findById(Long id) { - - return em.find(Customer.class, id); - } - - - /* - * (non-Javadoc) - * - * @see org.geecon.hades.before.CustomerRepository#findAll() - */ - @Override - @SuppressWarnings("unchecked") - public List findAll() { - - return em.createQuery("from Customer c").getResultList(); - } - - - /* - * (non-Javadoc) - * - * @see org.geecon.hades.before.CustomerRepository#findAll(int, int) - */ - @Override - @SuppressWarnings("unchecked") - public List findAll(int page, int pageSize) { - - Query query = em.createQuery("from Customer c"); - - query.setFirstResult(page * pageSize); - query.setMaxResults(pageSize); - - return query.getResultList(); - } - - - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.before.CustomerRepository#save(org.geecon.hades.before - * .Customer) - */ - @Override - public Customer save(Customer customer) { - - // Is new? - if (customer.getId() == null) { - em.persist(customer); - return customer; - } else { - return em.merge(customer); - } - } - - - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.before.CustomerRepository#findByLastname(java.lang.String - * , int, int) - */ - @Override - @SuppressWarnings("unchecked") - public List findByLastname(String lastname, int page, int pageSize) { - - Query query = em.createQuery("from Customer c where c.lastname = ?"); - - query.setParameter(1, lastname); - query.setFirstResult(page * pageSize); - query.setMaxResults(pageSize); - - return query.getResultList(); - } + @PersistenceContext + private EntityManager em; + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.CustomerService#findById(java.lang.Long) + */ + @Override + public Customer findById(Long id) { + return em.find(Customer.class, id); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.CustomerService#findAll() + */ + @Override + public List findAll() { + return em.createQuery("select c from Customer c", Customer.class).getResultList(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.CustomerService#findAll(int, int) + */ + @Override + public List findAll(int page, int pageSize) { + + TypedQuery query = em.createQuery("select c from Customer c", Customer.class); + + query.setFirstResult(page * pageSize); + query.setMaxResults(pageSize); + + return query.getResultList(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.CustomerService#save(org.springframework.data.jpa.showcase.core.Customer) + */ + @Override + @Transactional + public Customer save(Customer customer) { + + // Is new? + if (customer.getId() == null) { + em.persist(customer); + return customer; + } else { + return em.merge(customer); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.before.CustomerService#findByLastname(java.lang.String, int, int) + */ + @Override + public List findByLastname(String lastname, int page, int pageSize) { + + TypedQuery query = em.createQuery("select c from Customer c where c.lastname = ?1", Customer.class); + + query.setParameter(1, lastname); + query.setFirstResult(page * pageSize); + query.setMaxResults(pageSize); + + return query.getResultList(); + } } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Account.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Account.java index 2f613ad..097dc35 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Account.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Account.java @@ -10,38 +10,31 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; - /** * @author Oliver Gierke */ @Entity public class Account { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - @ManyToOne - private Customer customer; - - @Temporal(TemporalType.DATE) - private Date expiryDate; - - - public Long getId() { - - return id; - } - + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; - public Customer getCustomer() { + @ManyToOne + private Customer customer; - return customer; - } + @Temporal(TemporalType.DATE) + private Date expiryDate; + public Long getId() { + return id; + } - public Date getExpiryDate() { + public Customer getCustomer() { + return customer; + } - return expiryDate; - } + public Date getExpiryDate() { + return expiryDate; + } } diff --git a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Customer.java b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Customer.java index a6a6d66..77da23c 100644 --- a/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Customer.java +++ b/spring-data-jpa-showcase/src/main/java/org/springframework/data/jpa/showcase/core/Customer.java @@ -5,35 +5,28 @@ import javax.persistence.GenerationType; import javax.persistence.Id; - /** * @author Oliver Gierke */ @Entity public class Customer { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String firstname; - private String lastname; - - - public Long getId() { - - return id; - } - - - public String getFirstname() { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; - return firstname; - } + private String firstname; + private String lastname; + public Long getId() { + return id; + } - public String getLastname() { + public String getFirstname() { + return firstname; + } - return lastname; - } + public String getLastname() { + return lastname; + } } diff --git a/spring-data-jpa-showcase/src/main/resources/META-INF/persistence.xml b/spring-data-jpa-showcase/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index a3e6bac..0000000 --- a/spring-data-jpa-showcase/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/spring-data-jpa-showcase/src/main/resources/application-context-after.xml b/spring-data-jpa-showcase/src/main/resources/application-context-after.xml deleted file mode 100644 index 6565afb..0000000 --- a/spring-data-jpa-showcase/src/main/resources/application-context-after.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/spring-data-jpa-showcase/src/main/resources/application-context-before.xml b/spring-data-jpa-showcase/src/main/resources/application-context-before.xml deleted file mode 100644 index a6d0a13..0000000 --- a/spring-data-jpa-showcase/src/main/resources/application-context-before.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/spring-data-jpa-showcase/src/main/resources/data.sql b/spring-data-jpa-showcase/src/main/resources/data.sql index 1554c94..443923b 100644 --- a/spring-data-jpa-showcase/src/main/resources/data.sql +++ b/spring-data-jpa-showcase/src/main/resources/data.sql @@ -2,8 +2,8 @@ INSERT INTO Customer (id, firstname, lastname) VALUES (1, 'Dave', 'Matthews'); INSERT INTO Customer (id, firstname, lastname) VALUES (2, 'Carter', 'Beauford'); INSERT INTO Customer (id, firstname, lastname) VALUES (3, 'Stephan', 'Lassard'); -INSERT INTO Account (id, customer_id, expiryDate) VALUES (1, 1, '2010-12-31'); -INSERT INTO Account (id, customer_id, expiryDate) VALUES (2, 1, '2011-03-31'); +INSERT INTO Account (id, customer_id, expiry_date) VALUES (1, 1, '2010-12-31'); +INSERT INTO Account (id, customer_id, expiry_date) VALUES (2, 1, '2011-03-31'); INSERT INTO Customer (id, firstname, lastname) VALUES (4, 'Charly', 'Matthews'); INSERT INTO Customer (id, firstname, lastname) VALUES (5, 'Chris', 'Matthews'); diff --git a/spring-data-jpa-showcase/src/main/resources/infrastructure.xml b/spring-data-jpa-showcase/src/main/resources/infrastructure.xml deleted file mode 100644 index 0e0d662..0000000 --- a/spring-data-jpa-showcase/src/main/resources/infrastructure.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountDaoJdbcImpl.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountDaoJdbcImpl.java deleted file mode 100644 index e960a8a..0000000 --- a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountDaoJdbcImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.springframework.data.jpa.showcase.snippets; - -import org.joda.time.LocalDate; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; - - -/** - * @author Oliver Gierke - */ -@Repository -class AccountRepositoryJdbcImpl implements AccountRepositoryCustom { - - private JdbcTemplate template; - - - public void setTemplate(JdbcTemplate template) { - - this.template = template; - } - - - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.after.AccountDaoCustom#removedExpiredAccounts(org.joda - * .time.LocalDate) - */ - @Override - public void removedExpiredAccounts(LocalDate reference) { - - template.update("DELETE Account AS a WHERE a.expiryDate < ?", reference - .toDateMidnight().toDate()); - } -} diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountPredicates.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountPredicates.java new file mode 100644 index 0000000..828a0f2 --- /dev/null +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountPredicates.java @@ -0,0 +1,25 @@ +package org.springframework.data.jpa.showcase.snippets; + +import org.joda.time.LocalDate; +import org.springframework.data.jpa.showcase.core.Account; +import org.springframework.data.jpa.showcase.core.QAccount; + +import com.mysema.query.types.expr.BooleanExpression; + +/** + * Predicates for {@link Account}s. + * + * @author Oliver Gierke + */ +public class AccountPredicates { + + private static QAccount $ = QAccount.account; + + public static BooleanExpression isExpired() { + return expiresBefore(new LocalDate()); + } + + public static BooleanExpression expiresBefore(LocalDate date) { + return $.expiryDate.before(date.toDateTimeAtStartOfDay().toDate()); + } +} diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepository.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepository.java index 856862b..85520f7 100644 --- a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepository.java +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepository.java @@ -4,21 +4,24 @@ import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; -import org.springframework.data.repository.Repository; - +import org.springframework.data.querydsl.QueryDslPredicateExecutor; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.NoRepositoryBean; /** * Repository to manage {@link Account} instances. * * @author Oliver Gierke */ -public interface AccountRepository extends Repository, AccountRepositoryCustom { +@NoRepositoryBean +public interface AccountRepository extends CrudRepository, AccountRepositoryCustom, + QueryDslPredicateExecutor { - /** - * Returns all accounts belonging to the given {@link Customer}. - * - * @param customer - * @return - */ - List findByCustomer(Customer customer); + /** + * Returns all accounts belonging to the given {@link Customer}. + * + * @param customer + * @return + */ + List findByCustomer(Customer customer); } diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryCustom.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryCustom.java index 9e181e7..dcae0a5 100644 --- a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryCustom.java +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryCustom.java @@ -2,11 +2,10 @@ import org.joda.time.LocalDate; - /** * @author Oliver Gierke */ interface AccountRepositoryCustom { - void removedExpiredAccounts(LocalDate reference); + void removedExpiredAccounts(LocalDate reference); } diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryImpl.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryImpl.java index a528c37..9dce0b0 100644 --- a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryImpl.java +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryImpl.java @@ -12,36 +12,29 @@ import org.springframework.data.jpa.showcase.core.Account; import org.springframework.stereotype.Repository; - /** * @author Oliver Gierke */ @Repository class AccountRepositoryImpl implements AccountRepositoryCustom { - @PersistenceContext - private EntityManager em; - + @PersistenceContext private EntityManager em; - /* - * (non-Javadoc) - * - * @see - * org.geecon.hades.after.AccountDaoCustom#removedExpiredAccounts(org.joda - * .time.DateTime) - */ - @Override - public void removedExpiredAccounts(LocalDate reference) { + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.snippets.AccountRepositoryCustom#removedExpiredAccounts(org.joda.time.LocalDate) + */ + @Override + public void removedExpiredAccounts(LocalDate reference) { - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery query = cb.createQuery(Account.class); - Root account = query.from(Account.class); + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(Account.class); + Root account = query.from(Account.class); - query.where(cb.lessThan(account.get("expiryDate").as(Date.class), - reference.toDateMidnight().toDate())); + query.where(cb.lessThan(account.get("expiryDate").as(Date.class), reference.toDateTimeAtStartOfDay().toDate())); - for (Account each : em.createQuery(query).getResultList()) { - em.remove(each); - } - } + for (Account each : em.createQuery(query).getResultList()) { + em.remove(each); + } + } } diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryJdbcImpl.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryJdbcImpl.java new file mode 100644 index 0000000..bb6448f --- /dev/null +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/AccountRepositoryJdbcImpl.java @@ -0,0 +1,27 @@ +package org.springframework.data.jpa.showcase.snippets; + +import org.joda.time.LocalDate; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +/** + * @author Oliver Gierke + */ +@Repository +class AccountRepositoryJdbcImpl implements AccountRepositoryCustom { + + private JdbcTemplate template; + + public void setTemplate(JdbcTemplate template) { + this.template = template; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.showcase.snippets.AccountRepositoryCustom#removedExpiredAccounts(org.joda.time.LocalDate) + */ + @Override + public void removedExpiredAccounts(LocalDate reference) { + template.update("DELETE Account AS a WHERE a.expiryDate < ?", reference.toDateTimeAtStartOfDay().toDate()); + } +} diff --git a/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/CustomerSpecifications.java b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/CustomerSpecifications.java new file mode 100644 index 0000000..34e0c46 --- /dev/null +++ b/spring-data-jpa-showcase/src/snippets/java/org/springframework/data/jpa/showcase/snippets/CustomerSpecifications.java @@ -0,0 +1,45 @@ +package org.springframework.data.jpa.showcase.snippets; + +import java.util.Date; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.joda.time.LocalDate; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.showcase.core.Account; +import org.springframework.data.jpa.showcase.core.Customer; + +/** + * Collection of {@link Specification} implementations. + * + * @author Oliver Gierke + */ +public class CustomerSpecifications { + + /** + * All customers with an {@link Account} expiring before the given date. + * + * @param date + * @return + */ + public static Specification accountExpiresBefore(final LocalDate date) { + + return new Specification() { + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + + Root accounts = query.from(Account.class); + Path expiryDate = accounts. get("expiryDate"); + Predicate customerIsAccountOwner = cb.equal(accounts. get("customer"), root); + Predicate accountExpiryDateBefore = cb.lessThan(expiryDate, date.toDateTimeAtStartOfDay().toDate()); + + return cb.and(customerIsAccountOwner, accountExpiryDateBefore); + } + }; + } +} diff --git a/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/AccountRepositoryIntegrationTest.java b/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/AccountRepositoryIntegrationTest.java index c8d39d2..752cf62 100644 --- a/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/AccountRepositoryIntegrationTest.java +++ b/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/AccountRepositoryIntegrationTest.java @@ -1,23 +1,34 @@ package org.springframework.data.jpa.showcase.snippets.test; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.jpa.showcase.snippets.AccountPredicates.*; import org.joda.time.LocalDate; +import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.snippets.AccountRepository; - /** * @author Oliver Gierke */ public abstract class AccountRepositoryIntegrationTest { - private AccountRepository accountDao; + private AccountRepository accountRepository; + + public void removesExpiredAccountsCorrectly() throws Exception { + + accountRepository.removedExpiredAccounts(new LocalDate(2011, 1, 1)); + assertThat(accountRepository.count(), is(1L)); + } + + public void findsExpiredAccounts() { + Account expired = accountRepository.findOne(1L); + Account valid = accountRepository.findOne(2L); - public void removesExpiredAccountsCorrectly() throws Exception { + Iterable findAll = accountRepository.findAll(expiresBefore(new LocalDate(2011, 3, 1))); - accountDao.removedExpiredAccounts(new LocalDate(2011, 1, 1)); - assertThat(accountDao.count(), is(1L)); - } + assertThat(findAll, hasItem(expired)); + assertThat(findAll, not(hasItem(valid))); + } } diff --git a/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/CustomerRepositoryIntegrationTest.java b/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/CustomerRepositoryIntegrationTest.java new file mode 100644 index 0000000..d51cf49 --- /dev/null +++ b/spring-data-jpa-showcase/src/test-snippets/java/org/springframework/data/jpa/showcase/snippets/test/CustomerRepositoryIntegrationTest.java @@ -0,0 +1,34 @@ +package org.springframework.data.jpa.showcase.snippets.test; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.jpa.domain.Specifications.*; +import static org.springframework.data.jpa.showcase.snippets.CustomerSpecifications.*; + +import java.util.List; + +import org.joda.time.LocalDate; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.showcase.after.CustomerRepository; +import org.springframework.data.jpa.showcase.core.Customer; + +/** + * Snippets to show the usage of {@link Specification}s. + * + * @author Oliver Gierke + */ +public class CustomerRepositoryIntegrationTest { + + private CustomerRepository repository; + + public void findsCustomersBySpecification() throws Exception { + + Customer dave = repository.findOne(1L); + + LocalDate expiryLimit = new LocalDate(2011, 3, 1); + List result = repository.findAll(where(accountExpiresBefore(expiryLimit))); + + assertThat(result.size(), is(1)); + assertThat(result, hasItems(dave)); + } +} diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/AbstractShowcaseTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/AbstractShowcaseTest.java new file mode 100644 index 0000000..16af1e0 --- /dev/null +++ b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/AbstractShowcaseTest.java @@ -0,0 +1,32 @@ +package org.springframework.data.jpa.showcase; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.showcase.AbstractShowcaseTest.TestConfig; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; +import org.springframework.test.context.transaction.BeforeTransaction; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author Oliver Gierke + */ +@SpringApplicationConfiguration(classes = TestConfig.class) +@Transactional +public abstract class AbstractShowcaseTest extends AbstractTransactionalJUnit4SpringContextTests { + + @Configuration + @EnableAutoConfiguration + @ComponentScan + static class TestConfig { + + } + + @BeforeTransaction + public void setupData() throws Exception { + + deleteFromTables("account", "customer"); + executeSqlScript("classpath:data.sql", false); + } +} diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/AccountRepositoryIntegrationTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/AccountRepositoryIntegrationTest.java index e985ca5..efcb9e3 100644 --- a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/AccountRepositoryIntegrationTest.java +++ b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/AccountRepositoryIntegrationTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2011-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. + */ package org.springframework.data.jpa.showcase.after; import static org.hamcrest.CoreMatchers.*; @@ -7,32 +22,34 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.showcase.core.AbstractShowcaseTest; +import org.springframework.data.jpa.showcase.AbstractShowcaseTest; import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; -import org.springframework.test.context.ContextConfiguration; - /** + * Integration tests for Spring Data JPA {@link AccountRepository}. + * * @author Oliver Gierke */ -@ContextConfiguration("classpath:application-context-after.xml") public class AccountRepositoryIntegrationTest extends AbstractShowcaseTest { - @Autowired - AccountRepository accountRepository; + @Autowired AccountRepository accountRepository; + @Autowired CustomerRepository customerRepository; - @Autowired - CustomerRepository customerRepository; + @Test + public void savesAccount() { + Account account = accountRepository.save(new Account()); + assertThat(account.getId(), is(notNullValue())); + } - @Test - public void findsCustomersAccounts() throws Exception { + @Test + public void findsCustomersAccounts() { - Customer customer = customerRepository.findById(1L); - List accounts = accountRepository.findByCustomer(customer); + Customer customer = customerRepository.findOne(1L); + List accounts = accountRepository.findByCustomer(customer); - assertFalse(accounts.isEmpty()); - assertThat(accounts.get(0).getCustomer(), is(customer)); - } + assertFalse(accounts.isEmpty()); + assertThat(accounts.get(0).getCustomer(), is(customer)); + } } diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/CustomerRepositoryIntegrationTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/CustomerRepositoryIntegrationTest.java index 40a9d2b..41e6359 100644 --- a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/CustomerRepositoryIntegrationTest.java +++ b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/after/CustomerRepositoryIntegrationTest.java @@ -1,56 +1,80 @@ +/* + * Copyright 2011-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. + */ package org.springframework.data.jpa.showcase.after; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.jpa.domain.Specifications.*; +import static org.springframework.data.jpa.showcase.snippets.CustomerSpecifications.*; import java.util.List; +import org.joda.time.LocalDate; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.jpa.showcase.core.AbstractShowcaseTest; +import org.springframework.data.jpa.showcase.AbstractShowcaseTest; import org.springframework.data.jpa.showcase.core.Customer; -import org.springframework.test.context.ContextConfiguration; - /** + * Integration tests for Spring Data JPA {@link CustomerRepository}. + * * @author Oliver Gierke */ -@ContextConfiguration("classpath:application-context-after.xml") public class CustomerRepositoryIntegrationTest extends AbstractShowcaseTest { - @Autowired - CustomerRepository repository; + @Autowired CustomerRepository repository; + + @Test + public void findsAllCustomers() throws Exception { + Iterable result = repository.findAll(); - @Test - public void findsAllCustomers() throws Exception { + assertThat(result, is(notNullValue())); + assertTrue(result.iterator().hasNext()); + } - List result = repository.findAll(); + @Test + public void findsFirstPageOfMatthews() throws Exception { - assertThat(result, is(notNullValue())); - assertFalse(result.isEmpty()); - } + Page customers = repository.findByLastname("Matthews", new PageRequest(0, 2)); + assertThat(customers.getContent().size(), is(2)); + assertFalse(customers.hasPreviousPage()); + } - @Test - public void findsFirstPageOfMatthews() throws Exception { + @Test + public void findsCustomerById() throws Exception { - Page customers = - repository.findByLastname("Matthews", new PageRequest(0, 2)); + Customer customer = repository.findOne(2L); - assertThat(customers.getContent().size(), is(2)); - assertFalse(customers.hasPreviousPage()); - } + assertThat(customer.getFirstname(), is("Carter")); + assertThat(customer.getLastname(), is("Beauford")); + } + @Test + public void findsCustomersBySpecification() throws Exception { - @Test - public void findsCustomerById() throws Exception { + Customer dave = repository.findOne(1L); - Customer customer = repository.findById(2L); + LocalDate expiryLimit = new LocalDate(2011, 3, 1); + List result = repository.findAll(where(accountExpiresBefore(expiryLimit))); - assertThat(customer.getFirstname(), is("Carter")); - assertThat(customer.getLastname(), is("Beauford")); - } + assertThat(result.size(), is(1)); + assertThat(result, hasItems(dave)); + } } diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/AccountServiceIntegrationTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/AccountServiceIntegrationTest.java index 98ccc81..134d012 100644 --- a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/AccountServiceIntegrationTest.java +++ b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/AccountServiceIntegrationTest.java @@ -1,39 +1,56 @@ +/* + * Copyright 2011-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. + */ package org.springframework.data.jpa.showcase.before; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.List; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.showcase.core.AbstractShowcaseTest; +import org.springframework.data.jpa.showcase.AbstractShowcaseTest; import org.springframework.data.jpa.showcase.core.Account; import org.springframework.data.jpa.showcase.core.Customer; -import org.springframework.test.context.ContextConfiguration; - /** + * Integration test for {@link AccountService}. + * * @author Oliver Gierke */ -@ContextConfiguration("classpath:application-context-before.xml") public class AccountServiceIntegrationTest extends AbstractShowcaseTest { - @Autowired - AccountService accountService; + @Autowired AccountService accountService; + @Autowired CustomerService customerService; - @Autowired - CustomerService customerService; + @Test + public void savesAccount() { + Account account = accountService.save(new Account()); + assertThat(account.getId(), is(notNullValue())); + } - @Test - public void testname() throws Exception { + @Test + public void testname() throws Exception { - Customer customer = customerService.findById(1L); + Customer customer = customerService.findById(1L); - List accounts = accountService.findByCustomer(customer); + List accounts = accountService.findByCustomer(customer); - assertFalse(accounts.isEmpty()); - assertThat(accounts.get(0).getCustomer(), is(customer)); - } + assertThat(accounts, is(not(empty()))); + assertThat(accounts.get(0).getCustomer(), is(customer)); + } } diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/CustomerServiceIntegrationTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/CustomerServiceIntegrationTest.java index eb552d7..2ada0d0 100644 --- a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/CustomerServiceIntegrationTest.java +++ b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/before/CustomerServiceIntegrationTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2011-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. + */ package org.springframework.data.jpa.showcase.before; import static org.hamcrest.CoreMatchers.*; @@ -7,46 +22,41 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.showcase.core.AbstractShowcaseTest; +import org.springframework.data.jpa.showcase.AbstractShowcaseTest; import org.springframework.data.jpa.showcase.core.Customer; -import org.springframework.test.context.ContextConfiguration; - /** + * Integration test for {@link CustomerService}. + * * @author Oliver Gierke */ -@ContextConfiguration("classpath:application-context-before.xml") public class CustomerServiceIntegrationTest extends AbstractShowcaseTest { - @Autowired - CustomerService repository; - - - @Test - public void findsAllCustomers() throws Exception { - - List result = repository.findAll(); + @Autowired CustomerService repository; - assertThat(result, is(notNullValue())); - assertFalse(result.isEmpty()); - } + @Test + public void findsAllCustomers() throws Exception { + List result = repository.findAll(); - @Test - public void findsPageOfMatthews() throws Exception { + assertThat(result, is(notNullValue())); + assertFalse(result.isEmpty()); + } - List customers = repository.findByLastname("Matthews", 0, 2); + @Test + public void findsPageOfMatthews() throws Exception { - assertThat(customers.size(), is(2)); - } + List customers = repository.findByLastname("Matthews", 0, 2); + assertThat(customers.size(), is(2)); + } - @Test - public void findsCustomerById() throws Exception { + @Test + public void findsCustomerById() throws Exception { - Customer customer = repository.findById(2L); + Customer customer = repository.findById(2L); - assertThat(customer.getFirstname(), is("Carter")); - assertThat(customer.getLastname(), is("Beauford")); - } + assertThat(customer.getFirstname(), is("Carter")); + assertThat(customer.getLastname(), is("Beauford")); + } } diff --git a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/core/AbstractShowcaseTest.java b/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/core/AbstractShowcaseTest.java deleted file mode 100644 index dc03fed..0000000 --- a/spring-data-jpa-showcase/src/test/java/org/springframework/data/jpa/showcase/core/AbstractShowcaseTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.springframework.data.jpa.showcase.core; - -import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; -import org.springframework.test.context.transaction.BeforeTransaction; - - -/** - * @author Oliver Gierke - */ -public abstract class AbstractShowcaseTest extends - AbstractTransactionalJUnit4SpringContextTests { - - @BeforeTransaction - public void setupData() throws Exception { - - if (countRowsInTable("Customer") == 0) { - executeSqlScript("classpath:data.sql", false); - } - } -} diff --git a/spring-data-jpa-showcase/src/test/resources/log4j.properties b/spring-data-jpa-showcase/src/test/resources/log4j.properties deleted file mode 100644 index 6c1f0d4..0000000 --- a/spring-data-jpa-showcase/src/test/resources/log4j.properties +++ /dev/null @@ -1,12 +0,0 @@ -# Direct log messages to stdout -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n - -# Root logger option -log4j.rootLogger=WARN, stdout - -# Hibernate logging options (INFO only shows startup messages) -#log4j.logger.org.springframework=INFO -log4j.logger.org.springframework.data=DEBUG \ No newline at end of file diff --git a/spring-data-jpa-showcase/src/test/resources/logback.xml b/spring-data-jpa-showcase/src/test/resources/logback.xml new file mode 100644 index 0000000..31cf72b --- /dev/null +++ b/spring-data-jpa-showcase/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + %d %5p %40.40c:%4L - %m%n + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-jpa-showcase/template.mf b/spring-data-jpa-showcase/template.mf deleted file mode 100644 index 84a1ebe..0000000 --- a/spring-data-jpa-showcase/template.mf +++ /dev/null @@ -1,19 +0,0 @@ -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.springframework.data.jpa.showcase -Bundle-Name: ${project.name} -Bundle-Vendor: SpringSource -Bundle-Version: ${project.version} -Bundle-RequiredExecutionEnvironment: J2SE-1.6 -Import-Package: - javax.sql;version="0.0.0", - org.hsqldb;version="[1.8.0,1.9.0)" -Export-Template: - org.springframework.data.jpa.sample.*;version="${project.version}" -Import-Template: - javax.persistence.*;version="${jpa.version:[=.=.=,+1.0.0)}", - org.springframework.*;version="${spring.version:[=.=.=.=,+1.0.0)}", - org.springframework.data.*;version="${project.version:[=.=.=.=,+1.0.0)}", - org.joda.time.*;version="${jodatime.version:[=.=.=,+1.0.0]}" -Import-Library: - org.springframework.spring;version="${spring.version:[=.=.=.=,+1.0.0)}", - org.hibernate.ejb;version="[3.5.6,4.0.0]"