diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/IUserDAO.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/IUserDAO.java new file mode 100644 index 0000000000..41a3716ec7 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/IUserDAO.java @@ -0,0 +1,12 @@ +package org.baeldung.persistence.dao; + +import java.util.List; +import java.util.Map; + +import org.baeldung.persistence.model.User; + +public interface IUserDAO { + List searchUser(Map params); + + void save(User entity); +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserDAO.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserDAO.java new file mode 100644 index 0000000000..c3f6107d05 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserDAO.java @@ -0,0 +1,49 @@ +package org.baeldung.persistence.dao; + +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.baeldung.persistence.model.User; +import org.springframework.stereotype.Repository; + +@Repository +public class UserDAO implements IUserDAO { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List searchUser(final Map params) { + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = builder.createQuery(User.class); + final Root r = query.from(User.class); + + Predicate predicate = builder.conjunction(); + + for (final Map.Entry param: params.entrySet()){ + if (param.getKey().equalsIgnoreCase("age")) { + predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), Integer.parseInt(param.getValue().toString()))); + } + else{ + predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%")); + } + } + query.where(predicate); + + final List result = entityManager.createQuery(query).getResultList(); + return result; + } + + @Override + public void save(final User entity) { + entityManager.persist(entity); + } + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserRepository.java new file mode 100644 index 0000000000..de7acf60d5 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserRepository.java @@ -0,0 +1,9 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecifications.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecifications.java new file mode 100644 index 0000000000..a0f545b158 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecifications.java @@ -0,0 +1,45 @@ +package org.baeldung.persistence.dao; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.model.User_; +import org.springframework.data.jpa.domain.Specification; + +public class UserSpecifications { + public static Specification firstNameIsLike(final String term) { + + return new Specification() { + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder cb) { + return cb.like(root.get(User_.firstName), "%"+term+"%"); + } + + }; + } + + public static Specification lastNameIsLike(final String term) { + + return new Specification() { + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder cb) { + return cb.like(root.get(User_.lastName), "%" + term + "%"); + } + + }; + } + + public static Specification ageIsGreaterThan(final int minAge) { + + return new Specification() { + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder cb) { + return cb.greaterThanOrEqualTo(root.get(User_.age), minAge); + } + + }; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java new file mode 100644 index 0000000000..dd7b6727ec --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java @@ -0,0 +1,46 @@ +package org.baeldung.persistence.dao; + +import static org.baeldung.persistence.dao.UserSpecifications.ageIsGreaterThan; +import static org.baeldung.persistence.dao.UserSpecifications.firstNameIsLike; +import static org.baeldung.persistence.dao.UserSpecifications.lastNameIsLike; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.baeldung.persistence.model.User; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; + +public class UserSpecificationsBuilder { + + public static Specification buildUserSpecs(final Map params) { + if (params.size() == 0) + return null; + + final List> specs = new ArrayList>(); + String key, value; + + for (final Map.Entry param : params.entrySet()) { + key = param.getKey(); + value = param.getValue().toString(); + if (key.equalsIgnoreCase("age")) { + specs.add(ageIsGreaterThan(Integer.parseInt(value))); + } else if (key.equalsIgnoreCase("firstName")) { + specs.add(firstNameIsLike(value)); + } else if (key.equalsIgnoreCase("lastName")) { + specs.add(lastNameIsLike(value)); + } + } + + if (specs.size() == 0) + return null; + + Specification result = specs.get(0); + for (int i = 1; i < specs.size(); i++) { + result = Specifications.where(result).and(specs.get(i)); + } + return result; + + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User.java new file mode 100644 index 0000000000..d220f4458e --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User.java @@ -0,0 +1,96 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String firstName; + + private String lastName; + + private String email; + + private int age; + + public User() { + super(); + } + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String username) { + email = username; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((email == null) ? 0 : email.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 User user = (User) obj; + if (!email.equals(user.email)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User_.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User_.java new file mode 100644 index 0000000000..c7b6ba2de8 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/model/User_.java @@ -0,0 +1,11 @@ +package org.baeldung.persistence.model; + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(User.class) +public class User_ { + public static volatile SingularAttribute firstName; + public static volatile SingularAttribute lastName; + public static volatile SingularAttribute age; +} \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/UserService.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/UserService.java new file mode 100644 index 0000000000..accf20ca5e --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/UserService.java @@ -0,0 +1,42 @@ +package org.baeldung.persistence.service.impl; + +import java.util.List; +import java.util.Map; + +import org.baeldung.persistence.dao.IUserDAO; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.dao.UserSpecificationsBuilder; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class UserService { + @Autowired + private IUserDAO dao; + + @Autowired + private UserRepository repository; + + public UserService() { + super(); + } + + public void saveUser(final User user) { + dao.save(user); + } + + public List searchUser(final Map params) { + return dao.searchUser(params); + } + + public List searchBySpecification(final Map params) { + final Specification spec = UserSpecificationsBuilder.buildUserSpecs(params); + if (spec == null) + return repository.findAll(); + return repository.findAll(spec); + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java new file mode 100644 index 0000000000..be1bc25b76 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java @@ -0,0 +1,69 @@ +package org.baeldung.web.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.service.impl.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class UserController { + + @Autowired + private UserService service; + + public UserController() { + super(); + } + + @RequestMapping(method = RequestMethod.GET, value = "/users") + @ResponseBody + public List findAll(@RequestParam(value = "search", required = false) final String search) { + final Map params = new HashMap(); + + if (search != null) { + final Pattern pattern = Pattern.compile("(\\w+?):(\\w+?),"); + final Matcher matcher = pattern.matcher(search + ","); + while (matcher.find()) { + params.put(matcher.group(1), matcher.group(2)); + } + } + return service.searchUser(params); + } + + @RequestMapping(method = RequestMethod.GET, value = "/users/spec") + @ResponseBody + public List findAllBySpecification(@RequestParam(value = "search", required = false) final String search) { + final Map params = new HashMap(); + + if (search != null) { + final Pattern pattern = Pattern.compile("(\\w+?):(\\w+?),"); + final Matcher matcher = pattern.matcher(search + ","); + while (matcher.find()) { + params.put(matcher.group(1), matcher.group(2)); + } + } + return service.searchBySpecification(params); + } + + @RequestMapping(method = RequestMethod.GET, value = "/users/new") + @ResponseBody + public long addUser(@RequestParam("first") final String first, @RequestParam("last") final String last, @RequestParam("age") final int age) { + final User user = new User(); + user.setFirstName(first); + user.setLastName(last); + user.setEmail("john@doe.com"); + user.setAge(age); + service.saveUser(user); + return user.getId(); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java new file mode 100644 index 0000000000..aec73e5f5f --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java @@ -0,0 +1,105 @@ +package org.baeldung.persistence.query; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.service.impl.UserService; +import org.baeldung.spring.PersistenceConfig; +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.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@Transactional +@TransactionConfiguration +public class JPACriteriaQueryTest { + + @Autowired + private UserService userService; + + private User userJohn; + + private User userTom; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("John"); + userJohn.setLastName("Doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + userService.saveUser(userJohn); + + userTom = new User(); + userTom.setFirstName("Tom"); + userTom.setLastName("Doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + userService.saveUser(userTom); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final Map params = new HashMap(); + params.put("firstName", "John"); + params.put("lastName", "Doe"); + + final List result = userService.searchUser(params); + + assertEquals(1, result.size()); + assertEquals(userJohn.getEmail(), result.get(0).getEmail()); + } + + @Test + public void givenLast_whenGettingListOfUsers_thenCorrect() { + final Map params = new HashMap(); + params.put("lastName", "doe"); + + final List result = userService.searchUser(params); + assertEquals(2, result.size()); + } + + @Test + public void givenLastAndAge_whenGettingListOfUsers_thenCorrect() { + final Map params = new HashMap(); + params.put("lastName", "doe"); + params.put("age", "25"); + + final List result = userService.searchUser(params); + + assertEquals(1, result.size()); + assertEquals(userTom.getEmail(), result.get(0).getEmail()); + } + + @Test + public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect() { + final Map params = new HashMap(); + params.put("firstName", "Adam"); + params.put("lastName", "Fox"); + + final List result = userService.searchUser(params); + assertEquals(0, result.size()); + } + + @Test + public void givenPartialFirst_whenGettingListOfUsers_thenCorrect() { + final Map params = new HashMap(); + params.put("firstName", "jo"); + + final List result = userService.searchUser(params); + + assertEquals(1, result.size()); + assertEquals(userJohn.getEmail(), result.get(0).getEmail()); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java new file mode 100644 index 0000000000..9a942780cf --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java @@ -0,0 +1,89 @@ +package org.baeldung.persistence.query; + +import static org.baeldung.persistence.dao.UserSpecifications.ageIsGreaterThan; +import static org.baeldung.persistence.dao.UserSpecifications.firstNameIsLike; +import static org.baeldung.persistence.dao.UserSpecifications.lastNameIsLike; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.User; +import org.baeldung.spring.PersistenceConfig; +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.domain.Specifications; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@Transactional +@TransactionConfiguration +public class JPASpecificationsTest { + + @Autowired + private UserRepository repository; + + private User userJohn; + + private User userTom; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("John"); + userJohn.setLastName("Doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("Tom"); + userTom.setLastName("Doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + repository.save(userTom); + } + + @Test + public void givenLast_whenGettingListOfUsers_thenCorrect() { + final List result = repository.findAll(lastNameIsLike("doe")); + assertEquals(2, result.size()); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final List result = repository.findAll(Specifications.where(lastNameIsLike("doe")).and(firstNameIsLike("john"))); + + assertEquals(1, result.size()); + assertEquals(userJohn.getEmail(), result.get(0).getEmail()); + } + + @Test + public void givenLastAndAge_whenGettingListOfUsers_thenCorrect() { + final List result = repository.findAll(Specifications.where(lastNameIsLike("doe")).and(ageIsGreaterThan(25))); + + assertEquals(1, result.size()); + assertEquals(userTom.getEmail(), result.get(0).getEmail()); + } + + @Test + public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect() { + final List result = repository.findAll(Specifications.where(lastNameIsLike("Adam")).and(firstNameIsLike("Fox"))); + assertEquals(0, result.size()); + } + + @Test + public void givenPartialFirst_whenGettingListOfUsers_thenCorrect() { + final List result = repository.findAll(firstNameIsLike("jo")); + + assertEquals(1, result.size()); + assertEquals(userJohn.getEmail(), result.get(0).getEmail()); + } +}