Spring Boot
Spring Boot
This is
a common design pattern that helps separate concerns and organize the code into logical
layers. Let me break down each layer of the architecture and explain its role:
Role: This layer is responsible for presenting the user interface (UI) of the application. In your
case, the HTML templates are used to render views for the user.
How it works:
o When the Spring Boot application starts, it serves these templates via the / or any
other URL endpoint.
o Thymeleaf or JSP can be used in Spring Boot to render the HTML pages.
o The user interacts with these pages through buttons, forms, etc., and those
interactions generate requests that are sent to the backend controllers.
Example:
</form>
Role: The controller layer handles incoming HTTP requests and sends the appropriate
responses. This layer acts as the interface between the frontend (HTML templates) and the
backend (Service layer).
How it works:
o The controller contains the endpoints (URLs) that map to specific methods in the
service layer. It listens for user actions like GET, POST, PUT, and DELETE requests.
o It processes the input (from the user, usually in the form of JSON or form data) and
returns a response, either by redirecting to another page, rendering a view, or
returning data (e.g., JSON).
o The controller typically does not contain business logic. Instead, it delegates the logic
to the service layer.
Example:
@RestController
@RequestMapping("/api")
@PostMapping("/employees")
}
}
Role: The service layer holds the business logic of the application. It performs operations like
validating input data, applying transformations, or interacting with the database.
How it works:
o This layer is typically where the core functionality resides, such as adding an
employee, updating records, calculating salaries, etc.
o The service layer calls methods from the repository layer to interact with the
database (data layer).
o It is a good practice to use interfaces in the service layer to allow better separation
of concerns, easier testing, and flexibility.
Example:
@Service
}
return employeeRepository.save(employee);
}
}
Role: The repository layer interacts directly with the database. It is responsible for
performing CRUD (Create, Read, Update, Delete) operations.
How it works:
o This layer abstracts the database interaction logic, using JPA repositories or Spring
Data JPA interfaces to define query methods that will interact with the database.
o The repository layer typically deals with entities (models that represent database
tables) and may return DTOs (Data Transfer Objects) for better performance or
structure.
o DAO (Data Access Object) is a pattern used to define operations to fetch data from
the database and return it to the service layer.
o DTO (Data Transfer Object) is an object that carries data between processes. It is
typically used to prevent exposing the entity directly to the client and to aggregate
data for better performance.
Example:
@Repository
}
Role: The entity layer represents the data structure stored in the database. In a typical Spring
Boot JPA application, entities are mapped to database tables.
How it works:
o This layer contains the classes annotated with @Entity that correspond to the
database tables.
o Entities are used by the repository to store and retrieve data from the database.
Example:
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
}
1. Frontend (HTML Templates): Renders UI and sends requests to the backend via HTTP (e.g.,
using form submissions or Ajax).
2. Controller: Handles HTTP requests, delegates business logic to the service layer, and sends
appropriate responses to the frontend.
3. Service: Contains the business logic and calls the repository to interact with the database. It
may also perform validation and transformations.
4. Repository (DAO/DTO): Interacts with the database and performs CRUD operations on
entities.
Flow of Operations:
4. The Service layer interacts with the Repository to access or modify data in the Database.
5. The Repository performs CRUD operations on Entities (such as Employee) in the database.
6. The Controller sends a response back to the Frontend, which updates the UI.
By dividing the application into these layers, you ensure separation of concerns, making the
application easier to maintain and extend.
Common dependencies from [Spring Initializr](https://start.spring.io/) and their uses:
1. Spring Web
Use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
---
Use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
---
Use:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
---
4. Lombok
Use:
Annotations:
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
---
5. MySQL Driver
Use:
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
---
6. Thymeleaf
Use:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
---
7. Spring Security
Use:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
---
Use:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
---
Use:
- Provides tools for unit and integration testing using JUnit, Mockito, and AssertJ.
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
---
Use:
- Enables validation for request payloads and form data using annotations like `@Valid` and
`@NotNull`.
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
---
These four components represent the core of the Spring MVC architecture. Together, they follow
the 3-layered architecture (Presentation, Service, and Data Access layers), which makes the
code organized and scalable.
Role: Models the data and maps it to a relational database using JPA (Java Persistence API).
Annotation: @Entity
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
@Id
Real-World Example: A "User" entity represents a user in an app, with fields like ID, name,
and email.
Example:
import org.springframework.data.jpa.repository.JpaRepository;
@Repository
Role: Calls the repository to fetch or save data and applies business rules.
Annotation: @Service
Example:
import org.springframework.stereotype.Service;
import java.util.List;
@Service
this.userRepository = userRepository;
return userRepository.findAll();
return userRepository.save(user);
Real-World Example: A rule like "don't allow duplicate emails" can be implemented in the
service.
Role: Receives API calls, delegates tasks to the service layer, and returns the result.
Example:
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
this.userService = userService;
@GetMapping
return userService.getAllUsers();
@PostMapping
return userService.createUser(user);
Explanation: UserController handles HTTP requests for getting and creating users by calling
UserService.
Real-World Example: When a user submits a form, the controller processes the data and
returns the response.
1. Client Request:
A client (browser/postman) sends an HTTP request (e.g., GET /users).
2. Controller Layer:
The UserController handles the request and calls the UserService for logic.
3. Service Layer:
The UserService processes the request, applies business rules, and calls the UserRepository.
4. Repository Layer:
The UserRepository interacts with the database to fetch/save data.
5. Entity Layer:
The User entity represents the database row, and the result is returned to the service and
controller.
6. Response:
The response is sent back to the client.
3. Diagram Representation
Client (Browser/Postman)
Separation of Concerns: Each layer handles a specific task, making code clean and organized.
Maintainability: Easier to test and debug specific layers without affecting the entire app.
5. Write a Service Layer – Create methods for fetching and saving data.
1. @Component Annotation
2. @Autowired Annotation
3. @Qualifier Annotation
4. @Primary Annotation
5. @SpringBootApplication
6. @Bean and @Configuration Annotations
7. @Controller, @Service and @Repository
8. @Lazy Annotation
9. @Scope Annotation
10. @Value Annotation
11. @PropertySource and PropertySources Annotations
12. @ConfigurationProperties Annotation
13. @Controller and @ResponseBody Annotations
14. @RestController Annotation
15. @RequestMapping Annotation
16. @GetMapping Annotation
17. @PostMapping and @RequestBody Annotations
18. @PutMapping Annotation
19. @DeleteMapping Annotation
20. @PathVariable Annotation
21. @RequestParam Annotation
22. @EnableAutoConfiguration
23. @ComponentScan
Spring Framework uses annotations to simplify the configuration and management of beans, define
services, and handle HTTP requests. Here's a detailed explanation of each of the annotations you've
listed, along with how they interconnect:
1. @Component Annotation
Purpose: Marks a class as a Spring bean. It's a generic stereotype annotation used for auto-
detecting and creating beans during component scanning.
Example:
@Component
// class definition
}
Connection: Any class annotated with @Component will be registered as a Spring bean and
can be injected using @Autowired.
2. @Autowired Annotation
Purpose: Used to inject dependencies automatically into Spring beans. It can be applied to
constructors, fields, or methods.
Example:
@Autowired
Connection: Automatically injects a matching bean (e.g., @Component) into the dependent
class.
3. @Qualifier Annotation
Purpose: Used with @Autowired to specify which bean to inject when multiple beans of the
same type exist.
Example:
@Autowired
@Qualifier("myBean1")
Connection: Resolves ambiguity by explicitly specifying the bean name when there are
multiple candidates.
4. @Primary Annotation
Purpose: Marks a bean as the default candidate for autowiring when there are multiple
beans of the same type.
Example:
@Primary
@Bean
}
Connection: @Autowired will inject the bean marked with @Primary when no @Qualifier is
provided.
5. @SpringBootApplication
Example:
@SpringBootApplication
SpringApplication.run(MyApp.class, args);
}
}
Connection: Bootstraps the Spring context and enables component scanning, auto-
configuration, and application setup.
@Configuration: Marks a class as a configuration class that can contain bean definitions.
Example:
@Configuration
@Bean
}
}
Connection: @Configuration is used to define beans via @Bean, and they can be injected
using @Autowired.
Example:
@Controller
// controller methods
}
@Service
// service methods
}
@Repository
// repository methods
}
Connection: These annotations are specialized versions of @Component and help Spring
manage the roles of the classes.
8. @Lazy Annotation
Purpose: Marks a bean to be lazily initialized, meaning it will only be created when it's first
needed.
Example:
@Lazy
@Component
// class definition
}
Connection: Ensures the bean is created only when required, improving startup time.
9. @Scope Annotation
Example:
@Scope("prototype")
@Component
// class definition
}
Connection: Controls the lifecycle and visibility of beans within the Spring container.
Purpose: Injects values from properties files or expressions into fields, methods, or
constructor parameters.
Example:
@Value("${my.property}")
Example:
@PropertySource("classpath:application.properties")
@Configuration
// class definition
}
Connection: Allows Spring to load external properties files for dependency injection.
12. @ConfigurationProperties Annotation
Purpose: Binds the properties from external files (e.g., application.properties) into a Java
class.
Example:
@ConfigurationProperties(prefix = "my")
}
@ResponseBody: Tells Spring to return the object as the response body (useful for RESTful
APIs).
Example:
@Controller
@RequestMapping("/greeting")
@ResponseBody
}
}
Purpose: A combination of @Controller and @ResponseBody, used for RESTful web services.
Example:
@RestController
@GetMapping("/api")
}
Purpose: Maps HTTP requests to handler methods of MVC and REST controllers.
Example:
@RequestMapping("/hello")
}
Example:
@GetMapping("/greet")
return "Hello!";
}
Example:
@PostMapping("/submit")
}
Example:
@PutMapping("/update")
return "Updated!";
}
Example:
@DeleteMapping("/delete")
return "Deleted!";
}
Example:
@GetMapping("/user/{id}")
}
Example:
@GetMapping("/search")
}
Connection: Extracts query parameters from the URL.
22. @EnableAutoConfiguration
Purpose: Tells Spring Boot to automatically configure the application based on the
dependencies in the classpath.
Example: This is typically used by Spring Boot when running a standalone application.
23. @ComponentScan
Purpose: Tells Spring to scan the package for annotated classes (like @Component,
@Service, @Repository).
Example:
@ComponentScan("com.myapp")
@Configuration
// class definition
}
Start with the Basics: Begin by learning the most commonly used annotations like
@Component, @Autowired, @RequestMapping, and @Controller. These are foundational
and used across most Spring applications.
Practice in Projects: Implement each annotation in small projects to see how they work
together.
Understand Their Use Cases: Learn when to use each annotation based on its intended
purpose (e.g., @Controller for MVC, @Service for business logic).
Reference Spring Documentation: Always refer to the Spring documentation for more in-
depth explanations and examples.
1. MySQL Setup
FLUSH PRIVILEGES;
2. Application Configuration
In the application.properties file (you already have most of this), ensure the following properties are
correct:
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/employeerepo?
allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.implicit-
strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-
strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
3. Breakdown of Properties
4. Database Table
The Employee entity will automatically map to a table named employee_tbl in the database due to:
@Entity
@Table(name="employee_tbl")
If the table does not exist, Hibernate will create it based on the @Entity class.
SHOW TABLES;
6. Testing
7. Troubleshooting
Access denied – Check your root password or create a new MySQL user with the required
privileges.
EmployeeManagementApiApplication
EmployeeManagementApiApplication
package com.tsdotinc.employeemanagement.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
SpringApplication.run(EmployeeManagementApiApplication.class, args);
EmployeeController
package com.tsdotinc.employeemanagement.api.controller;
import com.tsdotinc.employeemanagement.api.model.Employee;
import com.tsdotinc.employeemanagement.api.service.EmployeeService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
this.employeeService = employeeService;
@PostMapping("/employees")
@GetMapping("/employees")
@GetMapping("/employees/{id}")
@PutMapping("/employees/{id}")
employee.setId(id);
@DeleteMapping("/employees/{id}")
public ResponseEntity<?> deleteEmployee(@PathVariable("id") Long id){
employeeService.deleteEmployee(id);
EmployeeNotFoundException
package com.tsdotinc.employeemanagement.api.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.io.Serial;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@Serial
super(message);
Employee
package com.tsdotinc.employeemanagement.api.model;
import jakarta.persistence.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serial;
import java.io.Serializable;
@Entity
@Table(name="employee_tbl")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Serial
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="Id")
@Column(name="First_Name")
@JsonProperty("firstName")
@Column(name="Last_Name")
@JsonProperty("lastName")
@Column(name="Email_Id")
@JsonProperty("emailId")
@JsonProperty("jobTitle")
@Column(name="Department_Name")
@JsonProperty("departmentName")
@Column(name="Phone")
@JsonProperty("phone")
EmployeeRepository
package com.tsdotinc.employeemanagement.api.repository;
import com.tsdotinc.employeemanagement.api.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
EmployeeService
package com.tsdotinc.employeemanagement.api.service;
import com.tsdotinc.employeemanagement.api.exception.EmployeeNotFoundException;
import com.tsdotinc.employeemanagement.api.model.Employee;
import com.tsdotinc.employeemanagement.api.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Autowired
return employeeRepository.save(employee);
return employeeRepository.findAll();
return employeeRepository.findEmployeeById(id)
return employeeRepository.save(employee);
.findById(id)
this.employeeRepository.delete(existingEmployee);
}
ApplicationProperties
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/employeerepo?
allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.implicit-
strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-
strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
EmployeeIntegrationTests
package com.tsdotinc.employeemanagement.api;
import com.tsdotinc.employeemanagement.api.service.EmployeeService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
class EmployeeIntegrationTests {
@Autowired
@Test
void contextLoads() {
assertThat(employeeService).isNotNull();
@Test
void testEmployeeService() {
assertThat(employee).isNotNull();
assertThat(employee.getFirstName()).isEqualTo("Morgan");
}
1. Create - Add New Employee
Endpoint:
POST /api/employees
json
Copy code
"firstName": "John",
"lastName": "Doe",
"emailId": "[email protected]",
"departmentName": "Engineering",
"phone": "123-456-7890"
Description:
It accepts an Employee object in the request body and saves it to the database through the
EmployeeService layer.
Endpoint:
GET /api/employees
json
Copy code
"id": 1,
"firstName": "John",
"lastName": "Doe",
"emailId": "[email protected]",
"departmentName": "Engineering",
"phone": "123-456-7890"
Description:
The getAllEmployees method in the controller fetches all records using findAllEmployees().
Endpoint:
GET /api/employees/{id}
Example:
GET /api/employees/1
json
Copy code
"id": 1,
"firstName": "John",
"lastName": "Doe",
"emailId": "[email protected]",
"departmentName": "Engineering",
"phone": "123-456-7890"
Description:
json
Copy code
"firstName": "Jane",
"lastName": "Doe",
"emailId": "[email protected]",
"departmentName": "Management",
"phone": "987-654-3210"
Example:
PUT /api/employees/1
Description:
The updateEmployee method accepts an employee object and updates it in the database by
ID.
Endpoint:
DELETE /api/employees/{id}
Example:
DELETE /api/employees/1
Description:
The deleteEmployee method finds the employee by ID and deletes them from the database.
You need to create a database where the application can store its data. In your case, the
configuration uses book as the database name.
3. Create Tables
Since you are using Hibernate (JPA) to manage your entities, you can allow Spring Boot to
automatically create the necessary tables in the database, thanks to the spring.jpa.hibernate.ddl-
auto=update property. This will create or update the database schema based on the entities you
have defined.
However, if you want to manually create the tables, here's an SQL script that corresponds to your
Book and MyBookList entities.
name VARCHAR(255),
author VARCHAR(255),
price VARCHAR(255)
);
name VARCHAR(255),
author VARCHAR(255),
price VARCHAR(255)
);
If you haven't already created a user with privileges for the book database, you can do that with the
following commands:
FLUSH PRIVILEGES;
You can verify the connection to the database by running the following command in MySQL:
SHOW TABLES;
This should display the tables you've created (Book and MyBooks) if everything is set up correctly.
Ensure that your MySQL server is running. You can start it using the following command (based on
your operating system):
Windows: Use MySQL Workbench or the Command Prompt with mysql.server start.
Linux/Mac: Run sudo service mysql start or sudo systemctl start mysql.
Once the database is set up, you can run your Spring Boot application and check the logs to ensure
the application successfully connects to the MySQL database and interacts with the tables.
Summary
Define the tables (Book and MyBooks) based on your entity models, or rely on Hibernate to
do this automatically.
Once these steps are completed, your Spring Boot application should be able to interact with the
MySQL database.
BookStore/
├── src/
│ ├── main/
│ │ ├── java/com/BookStore/
│ │ │ ├── controller/
│ │ │ │ ├── BookController.java
│ │ │ │ ├── MyBookListController.java
│ │ │ ├── entity/
│ │ │ │ ├── Book.java
│ │ │ │ ├── MyBookList.java
│ │ │ ├── repository/
│ │ │ │ ├── BookRepository.java
│ │ │ │ ├── MyBookRepository.java
│ │ │ ├── service/
│ │ │ │ ├── BookService.java
│ │ │ │ ├── MyBookListService.java
│ │ │
│ │ │
│ │ └── resources/
│ │ ├── static/
│ │ │ ├── css/
│ │ │ │ └── style.css
│ │ │ ├── js/
│ │ │ │ └── script.js
│ │ ├── templates/
│ │ │ ├── bookEdit.html
│ │ │ ├── bookList.html
│ │ │ ├── BookRegister.html
│ │ │ ├── home.html
│ │ │ └── myBooks.html
│ │
│ │ ├── application.properties
│ └── src/test/java
└── pom.xml
BookStore/
├── src/
│ ├── main/
│ │ ├── java/com/BookStore/
package com.bookStore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
SpringApplication.run(BookStoreApplication.class, args);
│ │ │ ├── controller/
│ │ │ │ ├── BookController.java
package com.bookStore.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import com.bookStore.entity.Book;
import com.bookStore.entity.MyBookList;
import com.bookStore.service.BookService;
import com.bookStore.service.MyBookListService;
import java.util.*;
@Controller
@Autowired
@Autowired
@GetMapping("/")
return "home";
@GetMapping("/book_register")
return "bookRegister";
@GetMapping("/available_books")
List<Book>list=service.getAllBook();
// m.setViewName("bookList");
// m.addObject("book",list);
@PostMapping("/save")
public String addBook(@ModelAttribute Book b) {
service.save(b);
return "redirect:/available_books";
@GetMapping("/my_books")
List<MyBookList>list=myBookService.getAllMyBooks();
model.addAttribute("book",list);
return "myBooks";
@RequestMapping("/mylist/{id}")
Book b=service.getBookById(id);
myBookService.saveMyBooks(mb);
return "redirect:/my_books";
@RequestMapping("/editBook/{id}")
Book b=service.getBookById(id);
model.addAttribute("book",b);
return "bookEdit";
@RequestMapping("/deleteBook/{id}")
service.deleteById(id);
return "redirect:/available_books";
}
}
│ │ │ │ ├── MyBookListController.java
package com.bookStore.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.bookStore.service.MyBookListService;
@Controller
@Autowired
@RequestMapping("/deleteMyList/{id}")
service.deleteById(id);
return "redirect:/my_books";
│ │ │ ├── entity/
│ │ │ │ ├── Book.java
package com.bookStore.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
super();
this.id = id;
this.name = name;
this.author = author;
this.price = price;
public Book() {
super();
return id;
this.id = id;
return name;
}
this.name = name;
return author;
this.author = author;
return price;
this.price = price;
│ │ │ │ ├── MyBookList.java
package com.bookStore.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="MyBooks")
@Id
private int id;
public MyBookList() {
super();
super();
this.id = id;
this.name = name;
this.author = author;
this.price = price;
return id;
this.id = id;
return name;
this.name = name;
return author;
return price;
this.price = price;
│ │ │ ├── repository/
│ │ │ │ ├── BookRepository.java
package com.bookStore.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bookStore.entity.Book;
@Repository
│ │ │ │ ├── MyBookRepository.java
package com.bookStore.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bookStore.entity.MyBookList;
@Repository
│ │ │ ├── service/
│ │ │ │ ├── BookService.java
package com.bookStore.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bookStore.entity.Book;
import com.bookStore.repository.BookRepository;
@Service
@Autowired
bRepo.save(b);
return bRepo.findAll();
bRepo.deleteById(id);
│ │ │ │ ├── MyBookListService.java
package com.bookStore.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bookStore.entity.MyBookList;
import com.bookStore.repository.MyBookRepository;
@Service
@Autowired
mybook.save(book);
return mybook.findAll();
}
public void deleteById(int id) {
mybook.deleteById(id);
│ │ │
│ │ │
│ │ └── resources/
│ │ ├── static/
│ │ │ ├── css/
│ │ │ │ └── style.css
│ │ │ ├── js/
│ │ │ │ └── script.js
│ │ ├── templates/
│ │ │ ├── bookEdit.html
│ │ │ │ <!doctype html>
<head>
<meta charset="utf-8">
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<title>Book Store</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-dark">
<div class="container-fluid">
data-bs-toggle="collapse" data-bs-
target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
aria-current="page" href="/">Home</a></li>
href="available_books">Available Books</a></li>
Books</a></li> </ul>
</div>
</div>
</div>
</nav>
<div class="mb-3">
</div>
<div class="mb-3">
</div>
<div class="mb-3">
</div>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
integrity="sha384-
IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
crossorigin="anonymous"></script>
</body>
</html>
│ │ │ ├── bookList.html
│ │ │ │ <!doctype html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<title>Book Store</title>
</head>
<body>
<div class="container-fluid">
<span class="navbar-toggler-icon"></span>
</button>
<li class="nav-item">
</li>
<li class="nav-item">
<li class="nav-item">
</li>
</ul>
<div>
</div>
</div>
</div>
</nav>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Author</th>
<th scope="col">Price</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<td th:text="${b.id}"></td>
<td th:text="${b.name}"></td>
<td th:text="${b.author}"></td>
<td th:text="${b.price}"></td>
</td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
crossorigin="anonymous"></script>
</body>
</html>
│ │ │ ├── BookRegister.html
│ │ │ │ <!doctype html>
<head>
<meta charset="utf-8">
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<title>Book Store</title>
</head>
<body>
<div class="container-fluid">
data-bs-toggle="collapse" data-bs-
target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
aria-current="page" href="/">Home</a></li>
href="available_books">Available Books</a></li>
Books</a></li>
</ul>
<div>
<a class="nav-link text-white" href="book_register">New
Book
Register</a>
</div>
</div>
</div>
</nav>
<div class="mb-3">
</div>
<div class="mb-3">
</div>
<div class="mb-3">
</div>
</form>
</div>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script
src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
integrity="sha384-
IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
crossorigin="anonymous"></script>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
crossorigin="anonymous"></script>
</body>
</html>
│ │ │ ├── home.html
│ │ │ │ <!doctype html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<title>Book Store</title>
</head>
<body>
<div class="container-fluid">
<span class="navbar-toggler-icon"></span>
</button>
<li class="nav-item">
</li>
<li class="nav-item">
</li>
<li class="nav-item">
</li>
</ul>
<div>
</div>
</div>
</div>
</nav>
The graphic and typographic operators know this well, in reality all the professions
dealing with the universe of communication have a stable relationship with these words,
but what is it? Lorem ipsum is a dummy text without any sense. It is a sequence of Latin
words that, as they are positioned, do not form sentences with a complete sense, but give
life to a test text useful to fill spaces that will subsequently be occupied from ad hoc
text even if there are different versions distinguishable from the order in which the
</h6>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
crossorigin="anonymous"></script>
</body>
</html>
│ │ │ └── myBooks.html
│ │ <!doctype html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
<title>Book Store</title>
<script src="https://kit.fontawesome.com/0faddc1af8.js" crossorigin="anonymous"></script>
</head>
<body>
<div class="container-fluid">
<span class="navbar-toggler-icon"></span>
</button>
<li class="nav-item">
</li>
<li class="nav-item">
</li>
<li class="nav-item">
</li>
</ul>
<div>
</div>
</div>
</div>
</nav>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Author</th>
<th scope="col">Price</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<td th:text="${b.id}"></td>
<td th:text="${b.name}"></td>
<td th:text="${b.author}"></td>
<td th:text="${b.price}"></td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
crossorigin="anonymous"></script>
</body>
</html>
│ │ ├── application.properties
server.port=1001
spring.datasource.name=book
spring.datasource.url=jdbc:mysql://localhost:3306/book?ServerTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
│ └── src/test/java
package com.bookStore;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class BookStoreApplicationTests {
@Test
void contextLoads() {
└── pom.xml
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.5</version>
</parent>
<groupId>com.bookStore</groupId>
<artifactId>bookStore</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>bookStore</name>
<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-thymeleaf</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>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</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>
</plugin>
</plugins>
</build>
</project>