diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000000..1afb82bd42 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000000..017a39f7f5 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000000..f04507a101 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/thriftCompiler.xml b/.idea/thriftCompiler.xml new file mode 100644 index 0000000000..7bc123c6bc --- /dev/null +++ b/.idea/thriftCompiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-11-2/pom.xml b/core-java-modules/core-java-11-2/pom.xml index f43f8be442..5d7b1b7ddb 100644 --- a/core-java-modules/core-java-11-2/pom.xml +++ b/core-java-modules/core-java-11-2/pom.xml @@ -18,7 +18,7 @@ com.google.guava guava - ${guava.version} + ${version.guava} org.mock-server diff --git a/core-java-modules/core-java-11/pom.xml b/core-java-modules/core-java-11/pom.xml index c7a9259c36..a16fce9454 100644 --- a/core-java-modules/core-java-11/pom.xml +++ b/core-java-modules/core-java-11/pom.xml @@ -20,7 +20,7 @@ com.google.guava guava - ${guava.version} + ${version.guava} org.openjdk.jmh diff --git a/core-java-modules/core-java-datetime-conversion/pom.xml b/core-java-modules/core-java-datetime-conversion/pom.xml index fc16899a9b..8c16d41288 100644 --- a/core-java-modules/core-java-datetime-conversion/pom.xml +++ b/core-java-modules/core-java-datetime-conversion/pom.xml @@ -29,7 +29,7 @@ log4j log4j - ${log4j.version} + ${version.log4j} diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml index a9e2448391..e35efd2ecd 100644 --- a/core-java-modules/core-java-io/pom.xml +++ b/core-java-modules/core-java-io/pom.xml @@ -71,12 +71,12 @@ log4j log4j - ${log4j.version} + ${version.log4j} org.slf4j log4j-over-slf4j - ${slf4j.version} + ${version.slf4j} org.projectlombok diff --git a/core-java-modules/core-java-streams/pom.xml b/core-java-modules/core-java-streams/pom.xml index 66d50824a9..405da8f8d2 100644 --- a/core-java-modules/core-java-streams/pom.xml +++ b/core-java-modules/core-java-streams/pom.xml @@ -35,7 +35,7 @@ log4j log4j - ${log4j.version} + ${version.log4j} org.projectlombok diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 4178a8129b..817e092d33 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -18,7 +18,7 @@ core-java-8 core-java-8-2 core-java-11 - core-java-11-2 + core-java-annotations core-java-collections core-java-collections-2 diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index ba849ccd3f..24f895813e 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 parent-boot-2 - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT parent-boot-2 pom Parent for all Spring Boot 2 modules @@ -13,7 +13,7 @@ com.ossez parent-modules - 0.0.1 + 0.0.2-SNAPSHOT diff --git a/persistence-modules/activejdbc/pom.xml b/persistence-modules/activejdbc/pom.xml index e971c3859f..9a4298c59c 100644 --- a/persistence-modules/activejdbc/pom.xml +++ b/persistence-modules/activejdbc/pom.xml @@ -9,9 +9,9 @@ http://maven.apache.org - com.baeldung + com.ossez persistence-modules - 1.0.0-SNAPSHOT + 0.0.2-SNAPSHOT diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index 042f67118a..e2591c51a0 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -8,9 +8,9 @@ hibernate5 - com.baeldung + com.ossez persistence-modules - 1.0.0-SNAPSHOT + 0.0.2-SNAPSHOT diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 1cf9977737..c0467cdee2 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -9,70 +9,82 @@ com.ossez parent-modules - 1.0.0 + 0.0.2-SNAPSHOT + ../pom.xml activejdbc - apache-cayenne - core-java-persistence - deltaspike - elasticsearch - flyway - hbase - hibernate5 - hibernate-mapping - hibernate-ogm - hibernate-annotations - hibernate-jpa - hibernate-queries - hibernate-enterprise - influxdb - java-cassandra - java-cockroachdb - java-jdbi - java-jpa - java-jpa-2 - java-mongodb - jnosql - jpa-hibernate-cascade-type - liquibase - orientdb - persistence-libraries - querydsl - r2dbc - redis + + + + + + + + + + + + + + + + + + + + + + + + + + + + - solr - spring-boot-persistence-2 - spring-boot-mysql - spring-boot-persistence - spring-boot-persistence-h2 - spring-boot-persistence-mongodb - spring-data-cassandra - spring-data-cassandra-reactive - spring-data-couchbase-2 - spring-data-dynamodb - spring-data-eclipselink - spring-data-elasticsearch - spring-data-gemfire - spring-data-geode - spring-data-jpa - spring-data-jpa-2 - spring-data-jpa-3 - spring-data-jpa-4 - spring-data-keyvalue - spring-data-mongodb - spring-data-neo4j - spring-data-redis - spring-data-solr - spring-hibernate-3 - spring-hibernate-5 - spring-hibernate4 - spring-jpa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + spring-data-jpa-repo-2 + + + + + + + + + - spring-persistence-simple - spring-persistence-simple-2 + + diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md new file mode 100644 index 0000000000..6403510e6f --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -0,0 +1,9 @@ +## Spring Data JPA - Repositories + +### Relevant Articles: + +- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) +- [Performance Difference Between save() and saveAll() in Spring Data](https://www.baeldung.com/spring-data-save-saveall) +- [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries) +- [How to Access EntityManager with Spring Data](https://www.baeldung.com/spring-data-entitymanager) +- More articles: [[<-- prev]](../spring-data-jpa-repo) diff --git a/persistence-modules/spring-data-jpa-repo-2/pom.xml b/persistence-modules/spring-data-jpa-repo-2/pom.xml new file mode 100644 index 0000000000..aac12db474 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + spring-data-jpa-repo-2 + spring-data-jpa-repo-2 + + 11 + 11 + + + + com.ossez + parent-boot-2 + 0.0.2-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + javax.persistence + javax.persistence-api + + + org.springframework.data + spring-data-jpa + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + + + + com.google.guava + guava + ${version.guava} + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java new file mode 100644 index 0000000000..f8f42aa67c --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.data.persistence.customrepository; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CustomRepositoryApplication { + + public static void main(String[] args) { + SpringApplication.run(CustomRepositoryApplication.class, args); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java new file mode 100644 index 0000000000..ba217577f3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java @@ -0,0 +1,55 @@ +package com.baeldung.spring.data.persistence.customrepository.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class User { + + @Id + @GeneratedValue + private Long id; + private String name; + private String email; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(email, user.email); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, email); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java new file mode 100644 index 0000000000..2c79e518b6 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; + +public interface CustomUserRepository { + + User customFindMethod(Long id); + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java new file mode 100644 index 0000000000..dc006580c1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.Objects; + +public class CustomUserRepositoryImpl implements CustomUserRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public User customFindMethod(Long id) { + return (User) entityManager.createQuery("FROM User u WHERE u.id = :id") + .setParameter("id", id) + .getSingleResult(); + } + + @PostConstruct + public void postConstruct() { + Objects.requireNonNull(entityManager); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java new file mode 100644 index 0000000000..d9f60015cc --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/UserRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.spring.data.persistence.customrepository.repository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository, CustomUserRepository { + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java new file mode 100644 index 0000000000..26a5723977 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/LikeApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.data.persistence.like; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LikeApplication { + + public static void main(String[] args) { + SpringApplication.run(LikeApplication.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java new file mode 100644 index 0000000000..f500b61a8a --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/model/Movie.java @@ -0,0 +1,58 @@ +package com.baeldung.spring.data.persistence.like.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Movie { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + private String title; + private String director; + private String rating; + private int duration; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java new file mode 100644 index 0000000000..57befb5943 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/like/repository/MovieRepository.java @@ -0,0 +1,40 @@ +package com.baeldung.spring.data.persistence.like.repository; + +import com.baeldung.spring.data.persistence.like.model.Movie; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface MovieRepository extends CrudRepository { + + List findByTitleContaining(String title); + + List findByTitleLike(String title); + + List findByTitleContains(String title); + + List findByTitleIsContaining(String title); + + List findByRatingStartsWith(String rating); + + List findByDirectorEndsWith(String director); + + List findByTitleContainingIgnoreCase(String title); + + List findByRatingNotContaining(String rating); + + List findByDirectorNotLike(String director); + + @Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%") + List searchByTitleLike(@Param("title") String title); + + @Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%") + List searchByRatingStartsWith(String rating); + + //Escaping works in SpringBoot >= 2.4.1 + //@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}") + @Query("SELECT m FROM Movie m WHERE m.director LIKE %:#{[0]}") + List searchByDirectorEndsWith(String director); +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/Foo.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/Foo.java new file mode 100644 index 0000000000..6833c4c556 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/Foo.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.data.persistence.repository; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class Foo implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/FooService.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/FooService.java new file mode 100644 index 0000000000..cb09a92b82 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/FooService.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.data.persistence.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class FooService implements IFooService { + @Autowired + private IFooDAO dao; + + @Override + public Foo create(Foo foo) { + return dao.save(foo); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooDAO.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooDAO.java new file mode 100644 index 0000000000..20a81e7bfa --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooDAO.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.data.persistence.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface IFooDAO extends JpaRepository { + + Foo findByName(String name); + + @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") + Foo retrieveByName(@Param("name") String name); +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooService.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooService.java new file mode 100644 index 0000000000..8ce6a2d1ae --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/IFooService.java @@ -0,0 +1,5 @@ +package com.baeldung.spring.data.persistence.repository; + +public interface IFooService { + Foo create(Foo foo); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/PersistenceConfig.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/PersistenceConfig.java new file mode 100644 index 0000000000..f73ea94658 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/repository/PersistenceConfig.java @@ -0,0 +1,81 @@ +package com.baeldung.spring.data.persistence.repository; + +import com.google.common.base.Preconditions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@PropertySource("classpath:persistence.properties") +@ComponentScan("com.baeldung.spring.data.persistence.repository") +//@ImportResource("classpath*:*springDataConfig.xml") +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.repository") +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan("com.baeldung.spring.data.persistence.repository"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + return hibernateProperties; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java new file mode 100644 index 0000000000..b6abdd2ed5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String title; + private String author; + + public Book(final String title, final String author) { + this.title = title; + this.author = author; + } + + public Book() { + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java new file mode 100644 index 0000000000..46cb8d3453 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; + +import java.util.ArrayList; +import java.util.List; + +@SpringBootApplication +public class BookApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(BookApplication.class); + + @Autowired + private BookRepository bookRepository; + + public static void main(String[] args) { + SpringApplication.run(BookApplication.class, args); + } + + @EventListener(ApplicationReadyEvent.class) + public void executePerformanceBenchmark() { + + int bookCount = 10000; + + long start = System.currentTimeMillis(); + for (int i = 0; i < bookCount; i++) { + bookRepository.save(new Book("Book " + i, "Author " + i)); + } + long end = System.currentTimeMillis(); + bookRepository.deleteAll(); + + LOGGER.debug("It took {}ms to execute save() for {} books.", (end - start), bookCount); + + List bookList = new ArrayList<>(); + for (int i = 0; i < bookCount; i++) { + bookList.add(new Book("Book " + i, "Author " + i)); + } + + start = System.currentTimeMillis(); + bookRepository.saveAll(bookList); + end = System.currentTimeMillis(); + + LOGGER.debug("It took {}ms to execute saveAll() with {}} books.", (end - start), bookCount); + + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java new file mode 100644 index 0000000000..9db4a18796 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BookRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/application.properties new file mode 100644 index 0000000000..cb1eab9443 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties new file mode 100644 index 0000000000..05cb7a13b9 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/persistence.properties @@ -0,0 +1,9 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +jdbc.pass=sa + +# hibernate.X +hibernate.hbm2ddl.auto=create-drop +hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/springDataConfig.xml b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/springDataConfig.xml new file mode 100644 index 0000000000..b2616d9eae --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/resources/springDataConfig.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java new file mode 100644 index 0000000000..ed54225a14 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/customrepository/CustomRepositoryUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.data.persistence.customrepository; + +import com.baeldung.spring.data.persistence.customrepository.model.User; +import com.baeldung.spring.data.persistence.customrepository.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(classes = CustomRepositoryApplication.class) +class CustomRepositoryUnitTest { + + @Autowired + private UserRepository userRepository; + + @Test + void givenCustomRepository_whenInvokeCustomFindMethod_thenEntityIsFound() { + User user = new User(); + user.setEmail("foo@gmail.com"); + user.setName("userName"); + + User persistedUser = userRepository.save(user); + + assertEquals(persistedUser, userRepository.customFindMethod(user.getId())); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java new file mode 100644 index 0000000000..291926c127 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/like/MovieRepositoryIntegrationTest.java @@ -0,0 +1,91 @@ +package com.baeldung.spring.data.persistence.like; + +import com.baeldung.spring.data.persistence.like.model.Movie; +import com.baeldung.spring.data.persistence.like.repository.MovieRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.sql.DataSource; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; + +@RunWith(SpringRunner.class) +@Sql(scripts = { "/test-movie-data.sql" }) +@SpringBootTest(classes = LikeApplication.class) +@Sql(scripts = "/test-movie-cleanup.sql", executionPhase = AFTER_TEST_METHOD) +public class MovieRepositoryIntegrationTest { + @Autowired + private MovieRepository movieRepository; + + @Autowired + private DataSource dataSource; + + @Test + public void givenPartialTitle_WhenFindByTitleContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleLike("%in%"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleIsContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleContains("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_WhenFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenFindByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialTitle_WhenFindByTitleContainingIgnoreCase_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContainingIgnoreCase("the"); + assertEquals(2, results.size()); + } + + @Test + public void givenPartialTitle_WhenSearchByTitleLike_ThenMoviesShouldReturn() { + List results = movieRepository.searchByTitleLike("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_SearchFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenSearchByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialRating_findByRatingNotContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingNotContaining("PG"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialDirector_WhenFindByDirectorNotLike_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorNotLike("An%"); + assertEquals(5, results.size()); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java new file mode 100644 index 0000000000..21990afb5e --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/java/com/baeldung/spring/data/persistence/repository/FooServiceIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.data.persistence.repository; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.sql.DataSource; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = PersistenceConfig.class) +public class FooServiceIntegrationTest { + + @Autowired + private IFooService service; + + @Autowired + private DataSource dataSource; + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo()); + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..8d4771e308 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + [%d{ISO8601}]-[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-cleanup.sql b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-cleanup.sql new file mode 100644 index 0000000000..90aa15307c --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-cleanup.sql @@ -0,0 +1 @@ +DELETE FROM Movie; \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-data.sql b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-data.sql new file mode 100644 index 0000000000..37f8e4fe64 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/test/resources/test-movie-data.sql @@ -0,0 +1,7 @@ +INSERT INTO movie(id, title, director, rating, duration) VALUES(1, 'Godzilla: King of the Monsters', ' Michael Dougherty', 'PG-13', 132); +INSERT INTO movie(id, title, director, rating, duration) VALUES(2, 'Avengers: Endgame', 'Anthony Russo', 'PG-13', 181); +INSERT INTO movie(id, title, director, rating, duration) VALUES(3, 'Captain Marvel', 'Anna Boden', 'PG-13', 123); +INSERT INTO movie(id, title, director, rating, duration) VALUES(4, 'Dumbo', 'Tim Burton', 'PG', 112); +INSERT INTO movie(id, title, director, rating, duration) VALUES(5, 'Booksmart', 'Olivia Wilde', 'R', 102); +INSERT INTO movie(id, title, director, rating, duration) VALUES(6, 'Aladdin', 'Guy Ritchie', 'PG', 128); +INSERT INTO movie(id, title, director, rating, duration) VALUES(7, 'The Sun Is Also a Star', 'Ry Russo-Young', 'PG-13', 100); diff --git a/pom.xml b/pom.xml index 118265cceb..569fc9b32c 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ + persistence-modules testing-modules toolkits @@ -55,9 +56,9 @@ UTF-8 - 1.7.30 - 1.2.17 - 2.2 + 1.7.36 + 1.2.17 + 2.18.0 2.8.0 @@ -71,7 +72,7 @@ 3.0.0 - 31.1-jre + 31.1-jre 4.3.5.Final