Get or Create in spring boot - spring

Using spring boot if how I can implement this logic (Get or Create)
Post request I will pass the student details if the student email exist return simple message "email already exist" and if not create new student record
I am using JpaRepository for my DB connection and I do have
Student class has the student structure data setter getter ...etc.
StudentController has registerNewStudent calls studentService.addNewStudent
StudentService has the addNewStudent method
addNewStudent should include some logic to check if the student email exist and if not it should create
What do you think ?

You can create a findByEmail method using JpaRepository. This method means select * from student where email="passedValue". If student with this email exits this method will return that student otherwise it will return null.
public interface StudentRepository extends JpaRepository<Student,String> {
Student findByEmail(String email); }
And then use this method:
public void saveStudent(Student student) {
Student savedStudent = studentRepository.findByEmail(student.getEmail());
if (savedStudent != null) {
System.out.println("email already exist");
} else {
studentRepository.save(student);
}
}
Hope this helps.

Related

I am getting internal server error dont konw reason for that

my code.....this was controller
controller
#Getmapping("/Transferabalance/{id}")
public List<Transaction> transfer(#PathVariable("Accbalance") long Accbalance) throws ResourceNotFoundException
{
List<Transaction> balance=Transservice.findByAccbalance(Accbalance);
if(balance==null)
throw new ResourceNotFoundException("NO BALANCE");
else
return balance;
}
This was service service
public List<Transaction> findByAccbalance(long Accbalance)
{
// TODO Auto-generated method stub
return transrepo.findByAccbalance(Accbalance);
}
transaction repository i used an query to retrive the elemnt from data base
public interface TransactionRepository extends CrudRepository<Transaction,Long>
{
#Query(value="select ACCBALANCE from TRANSACTION",nativeQuery = true)
List<Transaction> findByAccbalance(long Accbalance);
}
1st of all, CrudRepository itself provides you lots of methods to perform operation then why use JPQL though your query is simple.
you can simply use findByAccbalance(long Accbalance) that will return you expected result in your case.
List<Transaction> findByAccbalance(long Accbalance);
but if you wanna use Query then can you check with below Query:--
#Query(value="select c from TRANSACTION c")
List<Transaction> findByAccbalance(long Accbalance);

Querying mongodb collection SpringWebFlux with reactivemongodb

I am developing simple spring webflux demo application with reactive mongodb and i want to read all data of Employee by name except containing name field "joe","Sara","JOE","SARA" and i have following code like:
//repository interface
public interface EmployeeRepository extends ReactiveMongoRepository<Employee, String>{
Flux<Employee> findAllByName(String name);
}
//Service class
public class EmplyeeService
{
private EmployeeRepository employeeRepository;
public Flux<Employee> findAllByOrganizationName(String name)
{
return employeeRepository.findAllByName(name);
}
public Flux<String> getAllNameExceptSome(String name)
{
Employee emp1=new Employee();
List<Flux<Employee>> emp=Arrays.asList(employeeRepository.findAllByName(name));
Flux<Flux<Employee>> emp2=Flux.fromIterable(emp)
.filter(name->name.equalsIgnoreCase("joe"));
return emp2;
}
}
First of all, unless some particular situations, you should avoid these data structures:
List<Flux<Employee>>
Flux<Flux<Employee>>
However you are not leveraging Spring Data. You can achieve you result simply changing your repository to:
public interface EmployeeRepository extends ReactiveMongoRepository<Employee, String> {
// this find all Employee except those matching names provided as param
Flux<Employee> findAllByNameNotIn(List<String> nameList);
// this find all Employee matching names provided as param
Flux<Employee> findAllByNameIn(List<String> nameList);
}
Invoking this method you will obtain the list of Employee already filtered by name.

Spring cacheable annotation with multiple key

I have 2 ways to lookup a customer record (code below), customerGuid and customerId are 2 different fields in Customer object.
Suppose that i lookup customer by customerId once, is there a way for me to lookup customer by guid directly from cache without querying backend, Assuming both the methods return type is Customer.
public class CustomerLookup {
#Cacheable("customerCache")
public Customer getCustomerByGuid(final String customerGuid) {
// some implementation here...
}
#Cacheable("customerCache")
public Customer getCustomerByCustId(final String customerId) {
// some implementation here...
}
}
You can add a 2nd parameter to one method which will only serve as cache key. Example use customerId as key and proceed like this:
#Service
public class CustomerLookup {
#Autowired
#Lazy
private CustomerLookup self;
#CachePut("customerCache", key="#customerId")
public Customer getCustomerByGuid(final String customerGuid, String customerId) {
Customer customer = self.getCustomerByCustId(final String customerId);
//......
}
}
Note the self-injection of CustomerLookup if you don't do that the cache won't work when you call the getCustomerByCustId(final String customerId) method in getCustomerByGuid. Also note the #CachePut instead of #Cacheable on getCustomerByGuid, with this you are sure that this method will be called everytime.

How to throw exceptions on search methods in spring data jpa

I am using spring-data-jpa repositories for database operations. I want to throw exceptions if object doesn't exists in database for all methods in my repositories. For example Consider the following method in OrderRepository
findByCustomerAndPayment(Customer customer, Payment payment);
I want to query all orders based on customerId and paymentId. Both the objects are neccessry in the above query. But spring-data-rest returns null if I gave cutomerId doesn't exists in database. I expect spring-data-rest to throw exception if object doesn't exists in database.
How to achieve this?
You just need orElseThrow
orderRepository.findByCustomerAndPayment(customer, payment).orElseThrow(() -> new ResourceNotFoundException("customer", "id", customer.getId()));
If you're using Java 8, you can use Optional<Order> as the return type of the repository method. If the repository method returns an empty Optional calling get on it will throw a NoSuchElementException. Otherwise there is no support for throwing exceptions by repository methods if there are no results.
try {
Optional<Order> result = repository.findByCustomerAndPayment(customer,payment);
Order order = result.get();
} catch(NoSuchElementException e) {
// do something with the exception
}
You can make custom repository implementation like below:
public interface OrderRepositoryCustom {
Order findByCustomerAndPaymentRequired(Customer customer, Payment payment);
}
public class OrderRepositoryImpl implements OrderRepositoryCustom {
#Autowired
OrderRepository orderRepository;
#Override
public Order findByCustomerAndPaymentRequired(Customer customer, Payment payment) {
Order o = orderRepository.findByCustomerAndPayment(customer, payment);
if(o == null) {
throw new IncorrectResultSizeDataAccessException(1);
}
return o;
}
}
Your OrderRepository interface should extend customized:
public interface OrderRepository extends CrudRepository<Order, Long>, OrderRepositoryCustom {
Order findByCustomerAndPayment(Customer customer, Payment payment);
}
Edited
As IncorrectResultSizeDataAccessException is RuntimeException, then no need to throws declaration - i fixed that.
Use Optional together with orElseThrow.
Order findByCustomerAndPayment(Customer customer, Payment payment);
default Order findByCustomerAndPaymentOrThrow(Customer customer, Payment payment) {
return Optional.ofNullable(findByCustomerAndPayment(customer, payment)).orElseThrow();
};

How to define Spring Data Repository scope to Prototype?

I'm using Spring data jpa & hibernate for data access along with Spring boot. All the repository beans are singleton by default. I want to define the scope of all my repositories to Prototype. How can I do that?
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
Edit 1
The problem is related to domain object being shared in 2 different transactions which is causing my code to fail. I thought it is happening because repository beans are singleton. That's the reason I asked the question. Here is the detailed explanation of the scenario.
I have 2 entities User and UserSkill. User has 1-* relationship with UserSkills with lazy loading enabled on UserSkill relation.
In a UserAggregationService, I first make a call to fetch an individual user skill by id 123 which belongs to user with id 1.
public class UserAggregationService {
public List<Object> getAggregatedResults() {
resultList.add(userSkillService.getUserSkill(123));
//Throws Null Pointer Exception. See below for more details.
resultList.add(userService.get(1));
}
}
Implementation of UserSkillService method looks like
#Override
public UserSkillDTO getUserSkill(String id) {
UserSkill userSkill = userSkillService.get(id);
//Skills set to null avoid recursive DTO mapping. Dozer mapper is used
//for mapping.
userSkill.getUser().setSkills(null);
UserSkillDTO result = mapper.map(userSkill, UserSkillDTO.class);
return result;
}
In the call of user aggregation service, I call UserService to fetch userDetails. UserService code looks like
#Override
public UserDTO getById(String id) {
User user = userService.getByGuid(id);
List<UserSkillDTO> userSkillList = Lists.newArrayList();
//user.getSkills throws null pointer exception.
for (UserSkill uSkill : user.getSkills()) {
//Code emitted
}
....
//code removed for conciseness
return userDTO;
}
UserSkillService method implementation
public class UserSkillService {
#Override
#Transactional(propagation = Propagation.SUPPORTS)
public UserSkill get(String guid) throws PostNotFoundException {
UserSkill skill = userSkillRepository.findByGuid(guid);
if (skill == null) {
throw new SkillNotFoundException(guid);
}
return skill;
}
}
UserService method implementation:
public class UserService {
#Override
#Transactional(readOnly = true)
public User getByGuid(String guid) throws UserNotFoundException {
User user = userRepo.findByGuid(guid);
if (user == null) {
throw new UserNotFoundException(guid);
}
return user;
}
}
Spring boot auto configuration is used to instantiate entity manager factory and transaction manager. In the configuration file spring.jpa.* keys are used to connect to the database.
If I comment the below line of code, then I do not get the exception. I am unable to understand why change in the domain object is being affecting the object fetch in a different transaction.
userSkill.getUser().setSkills(null);
Please suggest If I have missed something.

Resources