diff --git a/pom.xml b/pom.xml index 857922310f..bd626b3ad0 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,7 @@ spring-data-neo4j spring-data-redis spring-data-rest + spring-data-solr spring-dispatcher-servlet spring-exceptions spring-freemarker diff --git a/spring-data-solr/pom.xml b/spring-data-solr/pom.xml new file mode 100644 index 0000000000..bd48a53d06 --- /dev/null +++ b/spring-data-solr/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + com.baeldung + spring-data-solr + 0.0.1-SNAPSHOT + jar + spring-data-solr + + + + UTF-8 + 4.2.5.RELEASE + 2.19.1 + 2.0.4.RELEASE + + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework.data + spring-data-solr + ${spring-data-solr} + + + org.springframework + spring-context + ${spring.version} + + + log4j + log4j + 1.2.16 + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + ${spring.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + + + + + + + diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java new file mode 100644 index 0000000000..1fe1e5468b --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.data.solr.config; + +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.solr.core.SolrTemplate; +import org.springframework.data.solr.repository.config.EnableSolrRepositories; + +@Configuration +@EnableSolrRepositories(basePackages = "com.baeldung.spring.data.solr.repository", namedQueriesLocation = "classpath:solr-named-queries.properties", multicoreSupport = true) +@ComponentScan +public class SolrConfig { + + @Bean + public SolrClient solrClient() { + return new HttpSolrClient("http://localhost:8983/solr"); + } + + @Bean + public SolrTemplate solrTemplate(SolrClient client) throws Exception { + return new SolrTemplate(client); + } +} diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java new file mode 100644 index 0000000000..7cd0890718 --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java @@ -0,0 +1,55 @@ +package com.baeldung.spring.data.solr.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.solr.core.mapping.Indexed; +import org.springframework.data.solr.core.mapping.SolrDocument; + +@SolrDocument(solrCoreName = "product") +public class Product { + + @Id + @Indexed(name = "id", type = "string") + private String id; + + @Indexed(name = "name", type = "string") + private String name; + + @Indexed(name = "category", type = "string") + private String category; + + @Indexed(name = "description", type = "string") + private String description; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java new file mode 100644 index 0000000000..01ec1fb909 --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.data.solr.repository; + +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.solr.repository.Query; +import org.springframework.data.solr.repository.SolrCrudRepository; + +import com.baeldung.spring.data.solr.model.Product; + +public interface ProductRepository extends SolrCrudRepository { + + public List findByName(String name); + + @Query("name:*?0* OR category:*?0* OR description:*?0*") + public Page findByCustomQuery(String searchTerm, Pageable pageable); + + @Query(name = "Product.findByNamedQuery") + public Page findByNamedQuery(String searchTerm, Pageable pageable); + +} diff --git a/spring-data-solr/src/main/resources/solr-named-queries.properties b/spring-data-solr/src/main/resources/solr-named-queries.properties new file mode 100644 index 0000000000..cec59cbebd --- /dev/null +++ b/spring-data-solr/src/main/resources/solr-named-queries.properties @@ -0,0 +1 @@ +Product.findByNamedQuery=name:*?0* OR category:*?0* OR description:*?0* \ No newline at end of file diff --git a/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java b/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..74d94ef91c --- /dev/null +++ b/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java @@ -0,0 +1,144 @@ +package com.baeldung.spring.data.solr.repo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.spring.data.solr.config.SolrConfig; +import com.baeldung.spring.data.solr.model.Product; +import com.baeldung.spring.data.solr.repository.ProductRepository; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = SolrConfig.class) +public class ProductRepositoryIntegrationTest { + + @Autowired + private ProductRepository productRepository; + + @Before + public void clearSolrData() { + productRepository.deleteAll(); + } + + @Test + public void whenSavingProduct_thenAvailableOnRetrieval() throws Exception { + final Product product = new Product(); + product.setId("P000089998"); + product.setName("Desk"); + product.setCategory("Furniture"); + product.setDescription("New Desk"); + productRepository.save(product); + final Product retrievedProduct = productRepository.findOne(product.getId()); + assertEquals(product.getId(), retrievedProduct.getId()); + } + + @Test + public void whenUpdatingProduct_thenChangeAvailableOnRetrieval() throws Exception { + final Product product = new Product(); + product.setId("P0001"); + product.setName("T-Shirt"); + product.setCategory("Kitchen"); + product.setDescription("New T-Shirt"); + productRepository.save(product); + + product.setCategory("Clothes"); + productRepository.save(product); + + final Product retrievedProduct = productRepository.findOne(product.getId()); + assertEquals(product.getCategory(), retrievedProduct.getCategory()); + } + + @Test + public void whenDeletingProduct_thenNotAvailableOnRetrieval() throws Exception { + final Product product = new Product(); + product.setId("P0001"); + product.setName("Desk"); + product.setCategory("Furniture"); + product.setDescription("New Desk"); + productRepository.save(product); + + productRepository.delete(product); + + Product retrievedProduct = productRepository.findOne(product.getId()); + assertNull(retrievedProduct); + + } + + @Test + public void whenFindByName_thenAvailableOnRetrieval() throws Exception { + Product phone = new Product(); + phone.setId("P0001"); + phone.setName("Phone"); + phone.setCategory("Electronics"); + phone.setDescription("New Phone"); + productRepository.save(phone); + + List retrievedProducts = productRepository.findByName("Phone"); + assertEquals(phone.getId(), retrievedProducts.get(0).getId()); + } + + @Test + public void whenSearchingProductsByQuery_thenAllMatchingProductsShouldAvialble() throws Exception { + final Product phone = new Product(); + phone.setId("P0001"); + phone.setName("Smart Phone"); + phone.setCategory("Electronics"); + phone.setDescription("New Item"); + productRepository.save(phone); + + final Product phoneCover = new Product(); + phoneCover.setId("P0002"); + phoneCover.setName("Cover"); + phoneCover.setCategory("Phone"); + phoneCover.setDescription("New Product"); + productRepository.save(phoneCover); + + final Product wirelessCharger = new Product(); + wirelessCharger.setId("P0003"); + wirelessCharger.setName("Charging Cable"); + wirelessCharger.setCategory("Cable"); + wirelessCharger.setDescription("Wireless Charger for Phone"); + productRepository.save(wirelessCharger); + + Page result = productRepository.findByCustomQuery("Phone", new PageRequest(0, 10)); + assertEquals(3, result.getNumberOfElements()); + } + + @Test + public void whenSearchingProductsByNamedQuery_thenAllMatchingProductsShouldAvialble() throws Exception { + final Product phone = new Product(); + phone.setId("P0001"); + phone.setName("Smart Phone"); + phone.setCategory("Electronics"); + phone.setDescription("New Item"); + productRepository.save(phone); + + final Product phoneCover = new Product(); + phoneCover.setId("P0002"); + phoneCover.setName("Cover"); + phoneCover.setCategory("Phone"); + phoneCover.setDescription("New Product"); + productRepository.save(phoneCover); + + final Product wirelessCharger = new Product(); + wirelessCharger.setId("P0003"); + wirelessCharger.setName("Charging Cable"); + wirelessCharger.setCategory("Cable"); + wirelessCharger.setDescription("Wireless Charger for Phone"); + productRepository.save(wirelessCharger); + + Page result = productRepository.findByNamedQuery("one", new PageRequest(0, 10)); + assertEquals(3, result.getNumberOfElements()); + } + +}