package net.petrikainulainen.spring.datajpa.service;
import net.petrikainulainen.spring.datajpa.dto.PersonDTO;
import net.petrikainulainen.spring.datajpa.model.Person;
import net.petrikainulainen.spring.datajpa.repository.PersonRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import static net.petrikainulainen.spring.datajpa.repository.PersonSpecifications.lastNameIsLike;
/**
* This implementation of the PersonService interface communicates with
* the database by using a Spring Data JPA repository.
* @author Petri Kainulainen
*/
@Service
public class RepositoryPersonService implements PersonService {
private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryPersonService.class);
protected static final int NUMBER_OF_PERSONS_PER_PAGE = 5;
@Resource
private PersonRepository personRepository;
@Transactional
@Override
public Person create(PersonDTO created) {
LOGGER.debug("Creating a new person with information: " + created);
Person person = Person.getBuilder(created.getFirstName(), created.getLastName()).build();
return personRepository.save(person);
}
@Transactional
@Override
public long count(String searchTerm) {
LOGGER.debug("Getting person count for search term: " + searchTerm);
//Passes the specification created by PersonSpecifications class to the repository.
return personRepository.count(lastNameIsLike(searchTerm));
}
@Transactional(rollbackFor = PersonNotFoundException.class)
@Override
public Person delete(Long personId) throws PersonNotFoundException {
LOGGER.debug("Deleting person with id: " + personId);
Person deleted = personRepository.findOne(personId);
if (deleted == null) {
LOGGER.debug("No person found with id: " + personId);
throw new PersonNotFoundException();
}
personRepository.delete(deleted);
return deleted;
}
@Transactional(readOnly = true)
@Override
public List<Person> findAll() {
LOGGER.debug("Finding all persons");
return personRepository.findAll(sortByLastNameAsc());
}
@Transactional(readOnly = true)
@Override
public Person findById(Long id) {
LOGGER.debug("Finding person by id: " + id);
return personRepository.findOne(id);
}
@Transactional(readOnly = true)
@Override
public List<Person> search(String searchTerm, int pageIndex) {
LOGGER.debug("Searching persons with search term: " + searchTerm);
//Passes the specification created by PersonSpecifications class and the page specification to the repository.
Page requestedPage = personRepository.findAll(lastNameIsLike(searchTerm), constructPageSpecification(pageIndex));
return requestedPage.getContent();
}
/**
* Returns a new object which specifies the the wanted result page.
* @param pageIndex The index of the wanted result page
* @return
*/
private Pageable constructPageSpecification(int pageIndex) {
Pageable pageSpecification = new PageRequest(pageIndex, NUMBER_OF_PERSONS_PER_PAGE, sortByLastNameAsc());
return pageSpecification;
}
/**
* Returns a Sort object which sorts persons in ascending order by using the last name.
* @return
*/
private Sort sortByLastNameAsc() {
return new Sort(Sort.Direction.ASC, "lastName");
}
@Transactional(rollbackFor = PersonNotFoundException.class)
@Override
public Person update(PersonDTO updated) throws PersonNotFoundException {
LOGGER.debug("Updating person with information: " + updated);
Person person = personRepository.findOne(updated.getId());
if (person == null) {
LOGGER.debug("No person found with id: " + updated.getId());
throw new PersonNotFoundException();
}
person.update(updated.getFirstName(), updated.getLastName());
return person;
}
/**
* This setter method should be used only by unit tests.
* @param personRepository
*/
protected void setPersonRepository(PersonRepository personRepository) {
this.personRepository = personRepository;
}
}