Spring Boot React Crud Example

Hey Learners, In this post we will learn Spring Boot React Crud full tutorials with video. This tutorials will be helpful for you Crud Operation Using Spring boot and React full stack.

Guys first watch this video after used this code you will be easily understand. In this tutorials i used backend spring boot for rest api devlop and frontend react.

Spring Boot React Crud Example Technologies

Backend : Spring Boot ,Rest Api

Frontend – React (React Hook, React Router 6.0 )

Tools : STS, Vscode

Database: Mysql

Server : Apache Tomcat Server

Spring Boot React Crud Example Video

Spring boot React Crud Example Source Code

Employee System Backend Source Code

EmployeeSystemBackendApplication.java

package com.becoder;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EmployeeSystemBackendApplication {

	public static void main(String[] args) {
		SpringApplication.run(EmployeeSystemBackendApplication.class, args);
	}

}

EmpController.java

package com.becoder.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import com.becoder.model.Emp;
import com.becoder.service.EmpService;

@CrossOrigin(origins = "http://localhost:3000")
@Controller
@RequestMapping("/api/v1")
public class EmpController {

	@Autowired
	private EmpService empService;

	@PostMapping("/save")
	public ResponseEntity<Emp> createEmp(@RequestBody Emp emp) {
		return new ResponseEntity<Emp>(empService.createEmp(emp), HttpStatus.CREATED);
	}

	@GetMapping("/")
	public ResponseEntity<List<Emp>> getAllEmp() {
		return new ResponseEntity<List<Emp>>(empService.getAllEmp(), HttpStatus.OK);
	}

	@GetMapping("/{id}")
	public ResponseEntity<Emp> getEmpById(@PathVariable int id) {
		return new ResponseEntity<Emp>(empService.getEmpById(id), HttpStatus.OK);
	}

	@GetMapping("/delete/{id}")
	public ResponseEntity<String> deleteEmp(@PathVariable int id) {

		empService.deleteEmp(id);
		return new ResponseEntity<String>("Delete Sucessfully", HttpStatus.OK);
	}

	@PostMapping("/update/{id}")
	public ResponseEntity<Emp> updateEmp(@PathVariable int id, @RequestBody Emp emp) {
		return new ResponseEntity<Emp>(empService.updateEmp(id, emp), HttpStatus.OK);
	}

}

Emp.java

package com.becoder.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;

@Entity
@Data
public class Emp {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	private String firstName;

	private String lastName;

	private String email;

	private String address;

	private Double salary;

}

EmpRepository.java

package com.becoder.respository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.becoder.model.Emp;

public interface EmpRepository extends JpaRepository<Emp, Integer> {

}

EmpService.java

package com.becoder.service;

import java.util.List;

import com.becoder.model.Emp;

public interface EmpService {

	public Emp createEmp(Emp emp);

	public List<Emp> getAllEmp();

	public Emp getEmpById(int id);

	public void deleteEmp(int id);

	public Emp updateEmp(int id, Emp emp);

}

EmpServiceImpl.java

package com.becoder.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.becoder.model.Emp;
import com.becoder.respository.EmpRepository;

@Service
public class EmpServiceImpl implements EmpService {

	@Autowired
	private EmpRepository empRepo;

	@Override
	public Emp createEmp(Emp emp) {
		return empRepo.save(emp);
	}

	@Override
	public List<Emp> getAllEmp() {

		return empRepo.findAll();
	}

	@Override
	public Emp getEmpById(int id) {
		return empRepo.findById(id).get();
	}

	@Override
	public void deleteEmp(int id) {
		Emp emp = empRepo.findById(id).get();
		if (emp != null) {
			empRepo.delete(emp);
		}
	}

	@Override
	public Emp updateEmp(int id, Emp emp) {

		Emp oldEmp = empRepo.findById(id).get();

		if (oldEmp != null) {
			emp.setId(id);
			return empRepo.save(emp);
		}

		return null;
	}

}

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/react_fullstack
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.becoder</groupId>
	<artifactId>Employee_System_Backend</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Employee_System_Backend</name>
	<description>Emp Rest Api</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Employee System React Frontend Code

AddEmp.jsx

import React from "react";
import { useState } from "react";
import empService from "../service/emp.service";

const AddEmp = () => {
  const [emp, setEmp] = useState({
    firstName: "",
    lastName: "",
    email: "",
    address: "",
    salary: "",
  });
  const [msg, setMsg] = useState("");

  const handleChange = (e) => {
    const value = e.target.value;
    setEmp({ ...emp, [e.target.name]: value });
  };

  const submitEmp = (e) => {
    e.preventDefault();

    empService
      .saveEmp(emp)
      .then((res) => {
        setMsg("Emp Added Sucessfully");
        setEmp({
          firstName: "",
          lastName: "",
          email: "",
          address: "",
          salary: "",
        });
      })
      .catch((error) => {
        console.log(error);
      });
  };

  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6 offset-md-3">
          <div className="card">
            <div className="card-header text-center fs-3">
              Add Emp
              {msg && <p className="text-success">{msg}</p>}
            </div>

            <div className="card-body">
              <form onSubmit={(e) => submitEmp(e)}>
                <div className="mb-3">
                  <label>Enter First Name</label>
                  <input
                    type="text"
                    className="form-control"
                    name="firstName"
                    value={emp.firstName}
                    onChange={(e) => handleChange(e)}
                  />
                </div>

                <div className="mb-3">
                  <label>Enter Last Name</label>
                  <input
                    type="text"
                    className="form-control"
                    name="lastName"
                    value={emp.lastName}
                    onChange={(e) => handleChange(e)}
                  />
                </div>

                <div className="mb-3">
                  <label>Enter Email </label>
                  <input
                    type="text"
                    className="form-control"
                    name="email"
                    value={emp.email}
                    onChange={(e) => handleChange(e)}
                  />
                </div>

                <div className="mb-3">
                  <label>Enter Address</label>
                  <input
                    type="text"
                    className="form-control"
                    name="address"
                    value={emp.address}
                    onChange={(e) => handleChange(e)}
                  />
                </div>

                <div className="mb-3">
                  <label>Enter Salary</label>
                  <input
                    type="number"
                    className="form-control"
                    name="salary"
                    value={emp.salary}
                    onChange={(e) => handleChange(e)}
                  />
                </div>

                <div className="text-center">
                  <button className="btn btn-success">Submit</button>
                  <input
                    type="Reset"
                    className="btn btn-danger ms-2"
                    value="Reset"
                  />
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default AddEmp;

EditEmp.jsx

import React, { useState } from "react";
import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import empService from "../service/emp.service";

const EditEmp = () => {
  const [emp, setEmp] = useState({
    id: "",
    firstName: "",
    lastName: "",
    email: "",
    address: "",
    salary: "",
  });
  const [msg, setMsg] = useState("");

  const data = useParams();
  const navigate = useNavigate();

  useEffect(() => {
    empService
      .getEmpById(data.id)
      .then((res) => {
        setEmp(res.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  const handleChange = (e) => {
    const value = e.target.value;
    setEmp({ ...emp, [e.target.name]: value });
  };

  const updateEmp = (e) => {
    e.preventDefault();
    empService
      .updateEmp(emp.id, emp)
      .then((res) => {
        navigate("/");
      })
      .catch((error) => {
        console.log(error);
      });
  };

  return (
    <div>
      <div className="container">
        <div className="row">
          <div className="col-md-6 offset-md-3">
            <div className="card">
              <div className="card-header text-center fs-3">
                Edit Emp
                {msg && <p className="text-success">{msg}</p>}
              </div>

              <div className="card-body">
                <form onSubmit={(e) => updateEmp(e)}>
                  <div className="mb-3">
                    <label>Enter First Name</label>
                    <input
                      type="text"
                      className="form-control"
                      name="firstName"
                      value={emp.firstName}
                      onChange={(e) => handleChange(e)}
                    />
                  </div>

                  <div className="mb-3">
                    <label>Enter Last Name</label>
                    <input
                      type="text"
                      className="form-control"
                      name="lastName"
                      value={emp.lastName}
                      onChange={(e) => handleChange(e)}
                    />
                  </div>

                  <div className="mb-3">
                    <label>Enter Email </label>
                    <input
                      type="text"
                      className="form-control"
                      name="email"
                      value={emp.email}
                      onChange={(e) => handleChange(e)}
                    />
                  </div>

                  <div className="mb-3">
                    <label>Enter Address</label>
                    <input
                      type="text"
                      className="form-control"
                      name="address"
                      value={emp.address}
                      onChange={(e) => handleChange(e)}
                    />
                  </div>

                  <div className="mb-3">
                    <label>Enter Salary</label>
                    <input
                      type="number"
                      className="form-control"
                      name="salary"
                      value={emp.salary}
                      onChange={(e) => handleChange(e)}
                    />
                  </div>

                  <div className="text-center">
                    <button className="btn btn-success">Submit</button>
                    <input
                      type="Reset"
                      className="btn btn-danger ms-2"
                      value="Reset"
                    />
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default EditEmp;

Home.jsx

import React from "react";
import { useState } from "react";
import { useEffect } from "react";
import empService from "../service/emp.service";
import { Link } from "react-router-dom";
const Home = () => {
  const [empList, setEmpList] = useState([]);
  const [msg, setMsg] = useState("");
  useEffect(() => {
    init();
  }, []);

  const init = () => {
    empService
      .getAllEmp()
      .then((res) => {
        console.log(res.data);
        setEmpList(res.data);
      })
      .catch((error) => {
        console.log(error);
      });
  };

  const deleteEmp = (id) => {
    empService
      .deleteEmp(id)
      .then((res) => {
        setMsg("Delete Sucessfully");
        init();
      })
      .catch((error) => {
        console.log(error);
      });
  };

  return (
    <div className="container">
      <h1 className="text-center mt-3">Emp System</h1>
      {msg && <p className="text-center text-success">{msg}</p>}
      <table class="table mt-5">
        <thead className="bg-light">
          <tr>
            <th scope="col">SL No</th>
            <th scope="col">First Name</th>
            <th scope="col">Last Name</th>
            <th scope="col">Email</th>
            <th scope="col">Address</th>
            <th scope="col">Salary</th>
            <th scope="col">Action</th>
          </tr>
        </thead>
        <tbody>
          {empList.map((e, num) => (
            <tr>
              <th scope="row">{num + 1}</th>
              <td>{e.firstName}</td>
              <td>{e.lastName}</td>
              <td>{e.email}</td>
              <td>{e.address}</td>
              <td>{e.salary}</td>
              <td>
                <Link to={"editEmp/" + e.id} className="btn btn-sm btn-primary">
                  Edit
                </Link>
                <a
                  onClick={() => deleteEmp(e.id)}
                  className="btn btn-sm btn-danger ms-2"
                >
                  Delete
                </a>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Home;

Navbar.js

import {Link} from "react-router-dom";

const Navbar = () => {
    return (
        <div>
            <nav className="navbar navbar-expand-lg navbar-dark bg-success">
                <div className="container-fluid">
                    <a className="navbar-brand" href="#">Emp System</a>
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                            <li className="nav-item">
                                <Link to="/" className="nav-link active" aria-current="page" >Home</Link>
                            </li>
                            <li className="nav-item">
                                <Link to="/addEmp" className="nav-link" href="#">Add Emp</Link>
                            </li>




                        </ul>

                    </div>
                </div>
            </nav>

        </div>
    );
}

export default Navbar;

emp.service.js

import axios from "axios";

const BASE_API_URL = "http://localhost:8080/api/v1";

class EmpService {

    saveEmp(emp) {
        return axios.post(BASE_API_URL + "/save", emp);
    }

    getAllEmp() {
        return axios.get(BASE_API_URL + "/");
    }

    getEmpById(id) {
        return axios.get(BASE_API_URL + "/" + id);
    }

    deleteEmp(id) {
        return axios.get(BASE_API_URL + "/delete/" + id);
    }

    updateEmp(id, emp) {
        return axios.post(BASE_API_URL + "/update/" + id, emp);
    }
}

export default new EmpService();

App.js


import './App.css';
import AddEmp from './components/AddEmp';
import Navbar from './components/Navbar';
import { Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import EditEmp from './components/EditEmp';

function App() {
  return (
    <div >
      <Navbar></Navbar>
      <Routes>
        <Route path="/" element={<Home />}></Route>
        <Route path="/addEmp" element={<AddEmp />}></Route>
        <Route path="/editEmp/:id" element={<EditEmp />}></Route>
      </Routes>
    </div>
  );
}

export default App;

package.json

{
  "name": "emp_ui",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^0.27.2",
    "bootstrap": "^5.2.0",
    "react": "^18.2.0",
    "react-bootstrap": "^2.5.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.3.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Leave a Comment