I am new to java and springboot. I am trying to create one CRUD application using springboot.
I am using MySQL for storing the data.
Employee Model -
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email_id")
private String emailId;
public Employee() {
}
public Employee(String firstName, String lastName, String emailId) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
}
Employee Repository -
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.raksh.springboot.model.Employee;
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
Employee Controller -
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.raksh.springboot.model.Employee;
import com.raksh.springboot.repository.EmployeeRepository;
#CrossOrigin(origins = "http://localhost:3000/")
#RestController
#RequestMapping("/api/v1/")
public class EmployeeController {
#Autowired
private EmployeeRepository employeeRepository;
// get all employees
#GetMapping("/employees")
public List<Employee> getAllEmployees(){
return employeeRepository.findAll();
}
}
The above controller is giving me the result in the JSON array of objects form as shown below
[
{
"id": 1,
"firstName": "Tony",
"lastName": "Stark",
"emailId": "tony#gmail.com"
},
{
"id": 2,
"firstName": "Thor",
"lastName": "Odinson",
"emailId": "thor#asgard.com"
}
]
But I need the response in the below form
{
total_items: 100,
has_more: true,
employees : {
1 : {
"id": 1,
"firstName": "Raksh",
"lastName": "Sindhe",
"emailId": "raksh#gmail.com"
},
2: {
"id": 2,
"firstName": "Thor",
"lastName": "Odinson",
"emailId": "thor#asgard.com"
}
}
}
Really appreciate the help.
You should create EmployeeResponse model (change the name as you see fit).
Add the additional fields you require.
The total_items could be calculated using list.size().
For the other field, I would add an additional query to the database for counting the number of rows, for example by id column.
compare if it's more than 100 and set the field to true.
You can see example here: Does Spring Data JPA have any way to count entites using method name resolving?
If in the "findAll" method you don't limit to 100 rows and you actually get all the employees and then move all except 100, you can set this field without the additional count query.
Simply you need to encapsulate the results in a DTO class and pass it back with the response.
total_items - can be inferred by the size of the list returned by the repository.
has_more - If you are using findAll() with repository call then you would get all the employees in the DB. Otherwise, you might have to introduce pagination with the repository.
employees - Include employees in a Map
ResponseDTO
public class ResponseDTO {
private int total_items;
private boolean has_more;
private Map<Integer, Employee> employees;
public ResponseDTO(int totalItems, boolean hasMore, Map<Integer, Employee> employees) {
this.total_items=totalItems;
this.has_more=hasMore;
this.employees=employees;
}
//constructors, getters, and setters
}
EmpoyeeController
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.raksh.springboot.model.Employee;
import com.raksh.springboot.repository.EmployeeRepository;
#CrossOrigin(origins = "http://localhost:3000/")
#RestController
#RequestMapping("/api/v1/")
public class EmployeeController {
#Autowired
private EmployeeRepository employeeRepository;
// get all employees
#GetMapping("/employees")
public List<Employee> getAllEmployees(){
Pageable employeePage = PageRequest.of(0, 100); //so you expect first 100 slice from all the employees in the DB.
Page<Employee> employees = employeeRepository.findAll(employeePage);
Map<Integer, Employee> employeeMap = getEmployeeMap(employees.getContent());
return new ResponseDTO(employees.getNumberOfElements(),employees.hasNext(),employeeMap );
}
private Map<Integer, Employee> getEmployeeMap(List<Employee> empoyees){
if(employees!=null && !empoyees.isEmpty){
Map<Integer, Employee> employeeMap = new HashMap<>();
for(Employee emp:empoyees){
employeeMap.put(emp.getId(),emp);
}
return employeeMap;
}
return null;
}
}
Related
I am trying to create a CRUD application using Spring-boot and Mongo DB.
I am getting error the in the update and delete operations
During Delete, there is a timestamp error showing and on update a new object is getting created instead of updating the existing object. I have attached the controller and service layer codes.
Can anyone please find a solution for this.
Controller Layer
package com.springrest.springrest.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.springrest.springrest.entities.Course;
import com.springrest.springrest.services.CourseService;
#CrossOrigin
#RestController
#RequestMapping("/api")
public class MyController {
#Autowired
private CourseService courseService;
#GetMapping("/courses")
public ResponseEntity<?> getCourses(){
return ResponseEntity.ok(this.courseService.GetCourses());
}
#PostMapping("/courses")
public ResponseEntity<?> addCourse(#RequestBody Course course)
{
Course save=this.courseService.addCourse(course);
return ResponseEntity.ok(save);
}
#GetMapping("/courses/{courseId}")
public ResponseEntity<?> getCourse(#PathVariable String courseId ){
Optional<Course> save=this.courseService.getCourse(Integer.parseInt(courseId));
return ResponseEntity.ok(save);
}
#PutMapping("/courses/{courseId}")
public ResponseEntity<?> updateCourse(#PathVariable String courseId,
#RequestBody Course course)
{
Optional<Course> save=Optional.ofNullable(this.courseService.updateCourse(Integer.parseInt
(courseId),course));
return ResponseEntity.ok(save);
}
#DeleteMapping("/courses/{courseId}")
public void deleteCourse(#PathVariable String courseId)
{
this.courseService.deleteCourse(Integer.parseInt(courseId));
//return ResponseEntity.ok(this.courseService.deleteCourse(Integer.parseInt(courseId)));
}
}
Service Layer
package com.springrest.springrest.services;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springrest.springrest.entities.Course;
import com.springrest.springrest.repository.CourseRepository;
#Service
public class CourseServiceimpl implements CourseService
{
#Autowired
private CourseRepository userlist;
public List<Course> GetCourses() {
return this.userlist.findAll();
}
public Course addCourse(Course course) {
return this.userlist.save(course);
}
public Optional<Course> getCourse(int courseId)
{
Optional<Course> c=this.userlist.findById(courseId);
return c;
}
#Override
public Course updateCourse(int courseId, Course course)
{
Course c=this.userlist.findById(courseId).get();
c.setId(course.getId());
c.setTitle(course.getTitle());
c.setDescription(course.getDescription());
return this.userlist.save(c);
}
#Override
public void deleteCourse(int courseId)
{
//Course c= this.userlist.findById(courseId).get();
this.userlist.deleteById(courseId);
}
}
Entity Layer
package com.springrest.springrest.entities;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
#Document(collection="Course")
public class Course {
#Field( name="id")
private int id;
#Field(name="title")
private String title;
#Field(name="description")
private String description;
public Course(int id, String title, String description) {
super();
this.id = id;
this.title = title;
this.description = description;
}
public Course() {
super();
}
#Override
public String toString() {
return "Course [id=" + id + ", title=" + title + ", description=" + description + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
This is the error I am getting on a Delete Request
{
"timestamp": "2022-11-09T18:45:58.630+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/api/courses/147"
}
Are you getting an error in get and save operations? Because although you inject CourseService in controller, you did not override get and save operations methods in CourseServiceimpl class.
I've built a spring boot rest api. However, when I try to test it in Postman, I am getting a 404 error. I have linked the code below. Please note that there might be a random #component annotation in some files. This was my tired brain trying anything it can.
Student.java
package StudentModel;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "Student")
public class Student {
public enum status {
PAID,
UNPAID,
PARTIAL
}
#Column
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
#Column(nullable = false)
private String FirstName;
#Column(nullable = false)
private String LastName;
#Column(nullable = false)
private long Phone;
#Column(nullable = false)
private String Email;
#Column(nullable = false)
private status PaymentStatus;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public long getPhone() {
return Phone;
}
public void setPhone(long phone) {
Phone = phone;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public status getPaymentStatus() {
return PaymentStatus;
}
public void setPaymentStatus(status paymentStatus) {
PaymentStatus = paymentStatus;
}
}
StudentController.java
package StudentController;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import StudentModel.Student;
import StudentService.StudentService;
#Component
#RestController
#RequestMapping("/api/v1")
public class StudentController {
#Autowired
private StudentService studentService;
#PostMapping("/api/v1/addStudent")
public Student addStudent(#RequestBody Student student) {
return studentService.saveStudent(student);
}
#PostMapping("/api/v1/addStudents")
public List<Student> addStudents(#RequestBody List<Student> students) {
return studentService.saveStudents(students);
}
#GetMapping("/api/v1/students")
public List<Student> findAllStudents(){
return studentService.getStudents();
}
#GetMapping("/api/v1/students/{id}")
public Student findStudentById(#PathVariable long id) {
return studentService.getStudentById(id);
}
#GetMapping("/api/v1/students/{name}")
public Student findStudentByFirstName(#PathVariable String FirstName) {
return studentService.getStudentByFirstName(FirstName);
}
#PutMapping("/api/v1/update")
public Student updateStudent(#RequestBody Student student) {
return studentService.updateStudent(student);
}
#DeleteMapping("/api/v1/delete/{id}")
public String deleteStudent(#PathVariable long id) {
return studentService.deleteStudent(id);
}
}
StudentService.java
package StudentService;
import java.util.List;
import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import StudentModel.Student;
import StudentRepository.StudentRepository;
#Component
#Service
#Transactional
public class StudentService {
#Autowired
private StudentRepository studentRepository;
public Student saveStudent(Student student) {
return studentRepository.save(student);
}
public List<Student> saveStudents(List<Student> students) {
return studentRepository.saveAll(students);
}
public List<Student> getStudents() {
return studentRepository.findAll();
}
public Student getStudentById(long id){
return studentRepository.getById(id);
}
public Student getStudentByFirstName(String FirstName){
return studentRepository.findByFirstName(FirstName);
}
public Student getStudentByLastName(String LastName){
return studentRepository.findByLastName(LastName);
}
public Student getStudentByEmail(String Email){
return studentRepository.findByEmail(Email);
}
public Student getStudentByPhone(long Phone){
return studentRepository.findByPhone(Phone);
}
public String deleteStudent(long id) {
studentRepository.deleteById(id);
return "Student Deleted";
}
public Student updateStudent (Student student) {
Student existingStudent = studentRepository.getById(student.getId());
existingStudent.setFirstName(student.getFirstName());
existingStudent.setLastName(student.getLastName());
existingStudent.setEmail(student.getEmail());
existingStudent.setPhone(student.getPhone());
existingStudent.setPaymentStatus(student.getPaymentStatus());
return studentRepository.save(existingStudent);
}
}
StudentRepository.java
package StudentRepository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import StudentModel.Student;
#Component
public interface StudentRepository extends JpaRepository <Student, Long>{
// Student saveStudent (Student student);
Student findByFirstName(String FirstName);
Student findByLastName(String LastName);
Student findByEmail(String Email);
Student findByPhone(long Phone);
// Student findById(long id);
}
StudentApplication.java
package com.BusyQA;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#SpringBootApplication
#ComponentScan
public class BusyQaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusyQaApplication.class, args);
}
}
Any help would be greatly appreciated. Thank you.
To make it work, you need some improvements:
For Controller (REST API requests):
remove #Component annotation;
remove /api/v1/ from request mappings;
add DTO to only transfer the required information;
fix the name of the variables, following the convention.
import java.util.ArrayList;
import java.util.List;
import com.example.demo.dto.StudentDTO;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.springframework.web.bind.annotation.*;
#RestController
#RequestMapping("/api/v1")
public class StudentController {
private final StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
#PostMapping("/addStudent")
public Student addStudent(#RequestBody StudentDTO studentDTO) {
Student student = new Student(studentDTO);
return studentService.saveStudent(student);
}
#PostMapping("/addStudents")
public List<Student> addStudents(#RequestBody List<Student> students) {
return studentService.saveStudents(students);
}
#GetMapping("/students")
public List<StudentDTO> findAllStudents() {
List<StudentDTO> studentDTOList = new ArrayList<>();
List<Student> studentList = studentService.getStudents();
for (Student student : studentList) {
StudentDTO studentDTO = new StudentDTO(student);
studentDTOList.add(studentDTO);
}
return studentDTOList;
}
#GetMapping("/students/id/{id}")
public Student findStudentById(#PathVariable long id) {
return studentService.getStudentById(id);
}
#GetMapping("/students/firstName/{firstName}")
public Student findStudentByFirstName(#PathVariable String firstName) {
return studentService.getStudentByFirstName(firstName);
}
#PutMapping("/update")
public Student updateStudent(#RequestBody StudentDTO studentDTO) {
Student student = new Student(studentDTO);
return studentService.updateStudent(student);
}
#DeleteMapping("/delete/{id}")
public String deleteStudent(#PathVariable long id) {
return studentService.deleteStudent(id);
}
}
For Service class (Business logic):
remove #Component annotation;
remove #Transactional annotation;
use findById() to retrieve an entity by its Id;
import java.util.List;
import java.util.Optional;
import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityNotFoundException;
#Service
public class StudentService {
private final StudentRepository studentRepository;
public StudentService(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
public Student saveStudent(Student student) {
return studentRepository.save(student);
}
public List<Student> saveStudents(List<Student> students) {
return studentRepository.saveAll(students);
}
public List<Student> getStudents() {
return studentRepository.findAll();
}
public Student getStudentById(long id) {
return studentRepository.findById(id).orElseThrow(EntityNotFoundException::new);
}
public Student getStudentByFirstName(String firstName) {
return studentRepository.findByFirstName(firstName);
}
public Student getStudentByLastName(String lastName) {
return studentRepository.findByLastName(lastName);
}
public Student getStudentByEmail(String email) {
return studentRepository.findByEmail(email);
}
public Student getStudentByPhone(long phone) {
return studentRepository.findByPhone(phone);
}
public String deleteStudent(long id) {
studentRepository.deleteById(id);
return "Student Deleted";
}
public Student updateStudent(Student student) {
Student existingStudent = studentRepository.getById(student.getId());
existingStudent.setFirstName(student.getFirstName());
existingStudent.setLastName(student.getLastName());
existingStudent.setEmail(student.getEmail());
existingStudent.setPhone(student.getPhone());
existingStudent.setPaymentStatus(student.getPaymentStatus());
return studentRepository.save(existingStudent);
}
}
The Model class:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.example.demo.dto.StudentDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Builder;
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
#Entity
public class Student {
public Student(StudentDTO studentDTO) {
this.id = studentDTO.getId();
this.firstName = studentDTO.getFirstName();
this.lastName = studentDTO.getLastName();
this.phone = studentDTO.getPhone();
this.email = studentDTO.getEmail();
this.paymentStatus = studentDTO.getPaymentStatus();
}
public enum Status {
PAID,
UNPAID,
PARTIAL
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private long id;
private String firstName;
private String lastName;
private long phone;
private String email;
private Status paymentStatus;
}
DTO class:
import com.example.demo.entity.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor
#JsonInclude(NON_NULL)
public class StudentDTO implements Serializable {
public StudentDTO(Student student) {
this.id = student.getId();
this.firstName = student.getFirstName();
this.lastName = student.getLastName();
this.phone = student.getPhone();
this.email = student.getEmail();
this.paymentStatus = student.getPaymentStatus();
}
private long id;
private String firstName;
private String lastName;
private long phone;
private String email;
private Student.Status paymentStatus;
}
The Repository class:
import com.example.demo.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Student findByFirstName(String firstName);
Student findByLastName(String lastName);
Student findByEmail(String email);
Student findByPhone(long phone);
}
and the main class of a Spring Boot application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
To test it, you can use endpoints by the same principle:
POST: localhost:8080/api/v1/addStudent
POST: localhost:8080/api/v1/addStudents
GET: localhost:8080/api/v1/students
GET: localhost:8080/api/v1/students/id/1
GET: localhost:8080/api/v1/students/firstName/testName
PUT: localhost:8080/api/v1/update
DELETE: localhost:8080/api/v1/delete/1
As Dilermando mentioned in the comments, your #RequestMapping("/api/v1") is setting its mapping, then you're extending onto that with #PostMapping("/api/v1/addStudent") making the address {url}/api/v1/api/v1/addStudent. You can resolve this by removing the /api/v1 from the Post/get mappings:
#RequestMapping("/api/v1")
public class StudentController {
#Autowired
private StudentService studentService;
#PostMapping("/addStudent")
public Student addStudent(#RequestBody Student student) {
return studentService.saveStudent(student);
}
...etc
}
There are 2 reason behind 404 not found
Problem 1
You main class is in com.BusyQA package and Controller class is in StudentController package so you have to scan controller class in main class.
Your StudentApplication.java class should become:
#SpringBootApplication
#ComponentScan(basePackageClasses = StudentController.class) // Scan the controller class in main class.
public class BusyQaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusyQaApplication.class, args);
}
}
Problem 2
Remove pre path /api/v1 from all url mapping in controller. Now your mapping url should become
#RestController
#RequestMapping("/api/v1")
public class StudentController {
#Autowired
private StudentService studentService;
#PostMapping("/addStudent")
#PostMapping("/addStudents")
#GetMapping("/students")
#GetMapping("/students/{id}")
#GetMapping("/students/{name}")
#PutMapping("/update")
#DeleteMapping("/delete/{id}")
}
This is another mistake in your code:
Remove the #Component annotation from controller.
Remove the #Component annotation from Service class.
Remove the #Component annotation from Repository interface and add #Repository annotation.
I have started with Spring Boot recently. I am facing issues while converting my Java Object to JSON in the desired format.
package com.we.springmvcboot.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.we.springmvcboot.Model.Todo;
import com.we.springmvcboot.Service.TodoService;
import com.we.springmvcboot.Service.UserNotesRepository;
import antlr.collections.List;
import java.sql.Date;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
#Controller
public class TodoController {
#Autowired
private TodoService TodoRepo;
#RequestMapping(value = "/loginUser", method = RequestMethod.POST)
public #ResponseBody HashMap<String, Object> createPerson(#RequestParam("email") String email) {
System.out.println(todoservice.findByEmail(email));
HashMap<String, Object> map = new HashMap<>();
map.put("Status", 200);
map.put("Message", "Request Successful");
map.put("Data", todoservice.findBySql(1));
return map;
}
}
package com.we.springmvcboot.Service;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.we.springmvcboot.Model.OrderResponse;
import com.we.springmvcboot.Model.Todo;
#Repository
public interface TodoRepo extends JpaRepository<Todo, Integer> {
#Query(value="SELECT Notes.notesID, Notes.Title, Notes.Message, Notes.Date, UserNotes.UserID from
UserNotes JOIN Notes on UserNotes.NotesID=Notes.NotesID where userID=?1", nativeQuery=true)
List<Object> getSqlbyuserID(int user);
}
I am getting the output as
{
"Status": 200,
"Message": "Request Successful",
"Data": [
[
1,
"First Note",
"By Rohan",
"2017-03-03",
1
],
[
2,
"Second Note",
"By Rohan",
"2017-03-03",
1
]
]
}
but I want the output in the following format
{
“Status” : 200/400,
“Message” : “Request Successful”,
“Data” : {
“userNotes” : [
{
“notesID” : 1,
“title” : “abc”,
“message” : “content”,
“date” : 29/07/2020
"userID : 1
},
{
“notesID” : 2,
“title” : “abc”,
“message” : “content”,
“date” : 28/07/2020
"userID" : 2
}
]
}
If you are just beginner to the Spring Boot then I would suggest following coding structure. You will get the expected output easy way.
TodoController.java
package com.test.app.web;
import com.test.app.service.TodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
#Controller
public class TodoController {
#Autowired
private TodoService todoService;
#PostMapping("/loginUser")
public #ResponseBody HashMap<String, Object> createPerson(#RequestParam("email") String email) {
HashMap<String, Object> map = new HashMap<>();
map.put("Status", 200);
map.put("Message", "Request Successful");
map.put("Data", todoService.findByEmail(email));
return map; // Here, I return any generic data object. instead of creating map for all the apis.
}
}
TodoService.java
package com.test.app.service;
import com.test.app.domain.User;
import com.test.app.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class TodoService {
#Autowired
private UserRepository userRepository;
public List<User> findByEmail(String email) {
// Add your business logic here if you want to modify the fetched data.
return userRepository.findAllByEmail(email);
}
}
UserRepository.java
package com.test.app.repository;
import com.test.app.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
// Here Use, JPA naming convention to reduce the overhead of writing the native query.
List<User> findAllByEmail(String email);
}
User.java
package com.test.app.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(name = "user")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "CREATION_TIMESTAMP", columnDefinition = "datetime")
#Temporal(TemporalType.TIMESTAMP)
private Date creationTimestamp;
#Column(name = "LAST_UPDATED_TIMESTAMP", columnDefinition = "datetime")
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdatedTimestamp;
#Column(name = "name")
private String name;
#Column(name = "middelName")
private String middelName;
#Column(name = "lastName")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "phoneNo")
private String phoneNo;
#Column(name = "contactPersonName")
private String contactPersonName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreationTimestamp() {
return creationTimestamp;
}
public void setCreationTimestamp(Date creationTimestamp) {
this.creationTimestamp = creationTimestamp;
}
public Date getLastUpdatedTimestamp() {
return lastUpdatedTimestamp;
}
public void setLastUpdatedTimestamp(Date lastUpdatedTimestamp) {
this.lastUpdatedTimestamp = lastUpdatedTimestamp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMiddelName() {
return middelName;
}
public void setMiddelName(String middelName) {
this.middelName = middelName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public String getContactPersonName() {
return contactPersonName;
}
public void setContactPersonName(String contactPersonName) {
this.contactPersonName = contactPersonName;
}
}
I hope, you will get the answer you are looking for.
You are sending a list of objects from List<Object> getSqlbyuserID(int user); and setting it to map.put("Data", todoservice.findBySql(1));.
You need to have another class userNotes to hold the values from getSqlbyuserID and set it in map.
I want retrieve user email from MySql database table using spring boot.i used findByEmailAndPassword in controller but it retrieve null value for email.
Here is my Code
controller
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.JPARepository;
import com.example.demo.pojo.regisbean;
#Controller
public class registerController {
regisbean pp;
#RequestMapping(value = "/")
public String mm() {
System.out.println("I am in m1 method");
return "index";
}
#RequestMapping(value = { "/register", "home" })
public String m1() {
System.out.println("I am in mm method");
return "register";
}
#Autowired
JPARepository jpaRepository;
#PostMapping("/register")
public String regis(#ModelAttribute regisbean rb)
{
System.out.println("I m in regis method");
regisbean b=jpaRepository.save(rb);
if(b!=null)
return "index";
else
return "fail";
}
#RequestMapping(value= {"/login1","login2"})
public String m2() {
System.out.println("i m in m2()");
return "login";
}
#PostMapping("/login")
public String login(#ModelAttribute regisbean rx,Model m) {
System.out.println("I am in Login");
regisbean re=jpaRepository.findByEmailAndPassword(rx.getEmail(), rx.getPassword());
if(re!=null)
{
m.addAttribute("email",rx.getEmail());
m.addAttribute("password",rx.getPassword());
System.out.println("yes");
return "loginsuccess";
}
else
{
System.out.println(rx.getEmail());
System.out.println("failed");
return "register";
}
}
}
pojo class
package com.example.demo.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "pro")
public class regisbean {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String name;
#Column
private String email;
#Column
private String phonenumber;
#Column
private String password;
public int getId() {
return id;
}
public void setId(int 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;
}
public String getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(String phonenumber) {
this.phonenumber = phonenumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Repository
package com.example.demo;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.pojo.regisbean;
public interface JPARepository extends CrudRepository<regisbean, Integer> {
public regisbean findByEmailAndPassword(String email,String password);
}
I was able to get your code to work by inserting a row in the table:
INSERT INTO pro (
id
,email
,name
,password
,phonenumber
)
VALUES (
0
,'user#domain.com'
,'Jim'
,'secret'
,'123-123-1234'
)
Then changing:
public String login(#ModelAttribute regisbean rx,Model m) {
to:
public String login(#RequestBody RegisBean rx,Model m) {
and POSTing the following request body to the /login resource:
{
"email": "user#domain.com",
"password": "secret"
}
I didn't have to make any changes to your Repo. I suspect your attempt was failing because RegisBean was never being initialized with any values and so the repo was asked to find a record with a null email and a null password.
I am trying to populate some entity objects in a very simple Hibernate example. My database consists of two tables, "Departments" (Id, Name) and "Employees" (Id, DepartmentsId, FirstName, LastName). My SQL query is simply a left join of Employees to Departments.
I have set up the annotations as specified in the Hibernate documentation, but whenever I try to serialize the entities Hibernate goes into an endless loop and eventually throws a StackOverFlowError exception. Someone answering another question of mine was able to determine that the stack overflow is happening because the "Department" object contains a set of "Employee" objects, which each contain a "Department" object, which contains a set of Employee objects, etc. etc.
This type of bidirectional relationship is supposed to be legal as per the documentation linked above (the "mappedBy" parameter in Department is supposed to clue Hibernate in; I have also tried using the "joinColumn" annotation that is commented out in the code below), and other things I have read indicate the Hibernate is supposed to be smart enough not to go into an endless loop in this situation, but it is not working for my example. Everything works fine if I change the bidirectional relationship to a unidirectional relationship by removing the Department object from the Employee class, but obviously this causes the loss of a lot of functionality.
I have also tried foregoing the annotations for the older xml mapping files and setting the "inverse" parameter for the child table, but it still produces the same problem. How can I get this bidirectional relationship working the way it is supposed to work?
Department:
package com.test.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.JoinTable;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.JoinColumn;
import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
#Entity
#Table(name="Departments"
,catalog="test"
)
public class Department implements java.io.Serializable {
private Integer id;
private String name;
public Set<Employee> employees = new HashSet<Employee>(0);
public Department() {
}
public Department(String name) {
this.name = name;
}
public Department(String name, Set employees) {
this.name = name;
this.employees = employees;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name="Name", nullable=false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch=FetchType.LAZY, mappedBy="department")
/*#OneToMany
#JoinColumn(name="DepartmentsId")*/
public Set<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(Set employees) {
this.employees = employees;
}
}
Employee:
package com.test.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.JoinTable;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="Employees"
,catalog="test"
)
public class Employee implements java.io.Serializable {
private Integer id;
private Department department;
private String firstName;
private String lastName;
public Employee() {
}
public Employee(Department department, String firstName, String lastName) {
this.department = department;
this.firstName = firstName;
this.lastName = lastName;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name="DepartmentsId", nullable=false, insertable=false, updatable=false)
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
#Column(name="FirstName", nullable=false)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="LastName", nullable=false)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Department Manager (Contains the HQL query):
package com.test.controller;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import com.test.model.Department;
import com.test.util.HibernateUtil;
public class DepartmentManager extends HibernateUtil {
public List<Department> list() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Department> set = null;
try {
Query q = session.createQuery("FROM Department d JOIN FETCH d.employees e");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
set = (List<Department>) q.list();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
session.getTransaction().commit();
return set;
}
}
In general, you should not serialize your entities. Circular dependencies and proxies make that hard. Instead, you should manually transfer the data you need to send to a DTO (a new data-only class), and serialize it instead. It won't have the lazy collections, proxies, and whatnot.
For complement the top response i did a generic convert who do the job for me, transfering the entity values to DTO object, you just have to make your dto fields with the same name from the mapped entity.
Here is the source code.
/**
* Atribui os valores de campos correspondentes de um objeto para um outro objeto de destino. Os
* campos do objeto de destino que ja estiverem preenchidos nao serao substituidos
*
* #param objetoOrigem
* #param objetoDestino
* #return
* #throws NegocioException
*/
public static <T1, T2> T2 convertEntity(T1 objetoOrigem, T2 objetoDestino) throws NegocioException {
if (objetoOrigem != null && objetoDestino != null) {
Class<? extends Object> classe = objetoOrigem.getClass();
Class<? extends Object> classeDestino = objetoDestino.getClass();
Field[] listaCampos = classe.getDeclaredFields();
for (int i = 0; i < listaCampos.length; i++) {
Field campo = listaCampos[i];
try {
Field campoDestino = classeDestino.getDeclaredField(campo.getName());
campo.setAccessible(true);
campoDestino.setAccessible(true);
atribuiValorAoDestino(objetoOrigem, objetoDestino, campo, campoDestino);
} catch (NoSuchFieldException e) {
LOGGER.log(Logger.Level.TRACE, (Object) e);
continue;
} catch (IllegalArgumentException | IllegalAccessException e) {
LOGGER.error(e.getMessage(), e);
throw new NegocioException(e.getMessage(), EnumTypeException.ERROR);
}
}
}
return objetoDestino;
}