Rest Unit 2 Cls Notes
Rest Unit 2 Cls Notes
Build Production
Building production involves a series of steps to prepare an application for deployment
and use in a live environment. Here's a general overview of the process:
1. Project Setup
● Version Control: Ensure your project is in a version control system like Git.
● Dependencies: Define and manage dependencies using tools like npm, pip,
Maven, etc.
2. Environment Configuration
3. Build Process
6. Deployment
8. Security
Building a production-ready Spring Boot application with JPA involves several key steps,
including setting up your development environment, writing and testing your code,
configuring your application, and deploying it. Here's a step-by-step guide:
1. Project Setup
2. Configure Your Database
3. Entity and Repository Setup
4. Service Layer
5. Controller Layer
6. Build and Test
7. Dockerize Your Application
8. Deploy to Production
9. Monitoring and Maintenance
Monitoring Tools
Logging
Error Tracking
10. Security
@Service Annotation
In an application, the business logic resides within the service layer so we use the
@Service Annotation to indicate that a class belongs to that layer. It is also a
specialization of @Component Annotation like the @Repository Annotation. One most
important thing about the @Service Annotation is it can be applied only to classes. It is
used to mark the class as a service provider. So overall @Service annotation is used with
classes that provide some business functionalities. Spring context will autodetect these
classes when annotation-based configuration and classpath scanning is used.
@Repository Annotation
@Repository Annotation is a specialization of @Component annotation which is used to
indicate that the class provides the mechanism for storage, retrieval, update, delete and
search operation on objects. Though it is a specialization of @Component annotation, so
Spring Repository classes are autodetected by spring framework through classpath
scanning. This annotation is a general-purpose stereotype annotation which very close to
the DAO pattern where DAO classes are responsible for providing CRUD operations on
database tables.
@Service Annotation is a
@Repository Annotation is also a
specialization of @Component
specialization of @Component Annotation.
Annotation.
It is used to mark the class as a It is used to mark the interface as DAO (Data
service provider. Access Object) provider.
To connect with the MySQL Database you have to write a bunch of lines. You can write the properties
like this
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: springuser
url: jdbc:mysql://${MYSQL_HOST:localhost}:3306/db_example
password: ThePassword
jpa:
hibernate:
ddl-auto: update
So to connect and perform CRUD operation with the MySQL DB with Spring Boot
application we have to just configure it inside the application.properties file as follows:
# Configuration for MySQL Database
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url = jdbc:mysql://localhost:3306/schooldb
(Datasource URL of your DB and "schooldb", here is your schema name)
JPA (Java Persistence API) and ORM (Object-Relational Mapping) are essential
concepts for managing and accessing relational databases in Java applications. Here’s an
overview of both:
● Entity Management: Defines how Java classes (entities) are mapped to database
tables.
● JPQL (Java Persistence Query Language): A query language similar to SQL
but operates on entities rather than database tables.
● EntityManager: The primary API for interacting with the persistence context,
managing entities, and performing operations.
● Transaction Management: Supports declarative and programmatic transaction
management.
Core Annotations
Benefits of ORM
● Hibernate: The most widely used ORM framework for Java. It implements JPA
and provides additional features like caching and custom query languages.
● EclipseLink: The reference implementation of JPA, providing a comprehensive
ORM solution.
● Apache OpenJPA: An open-source implementation of JPA with support for
various advanced features.
By incorporating ORM into Spring Boot apps, developers can improve code readability
(as we use high level Java objects), boost productivity (as an application developer, we no
longer focus on writing complex database queries), enhance portability (easily switch
between different databases with minimal code change) and achieve consistency (as ORM
layer enforces consistency in data operations). This is exactly why I said our app is going to
be healthy.
Spring Data JPA or JPA stands for Java Persistence API, so before looking into that, we
must know about ORM (Object Relation Mapping). So Object relation mapping is simply
the process of persisting any java object directly into a database table. Usually, the name
of the object being persisted becomes the name of the table, and each field within that
object becomes a column. With the table setup, each row corresponds to a record in the
application. Hibernate is one example of ORM. In short, JPA is the interface while
hibernate is the implementation.
The java persistence API provides a specification for persisting, reading, and managing
data from your java object to your relational tables in the database. JPA specifies the set
of rules and guidelines for developing interfaces that follow standards. Straight to the
point: JPA is just guidelines to implement ORM and there is no underlying code for the
implementation. Spring Data JPA is part of the spring framework. The goal of spring data
repository abstraction is to significantly reduce the amount of boilerplate code required to
implement a data access layer for various persistence stores. Spring Data JPA is not a JPA
provider, it is a library/framework that adds an extra layer of abstraction on the top of our
JPA provider line Hibernate.
1. Setting Up Dependencies
Add dependencies to your pom.xml for Spring Boot, JPA, and Hibernate:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2. Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=myusername
spring.datasource.password=mypassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
3. Defining Entities
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Column;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
4. Repository Interface
5. Service Layer
@Service: This annotation is used with classes that provide some business
functionalities. Spring context will autodetect these classes when annotation-based
configuration and classpath scanning is used. Here JPA repository has lots of predefined
generic methods to perform the database operation some are used in the below code.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
6. Controller Layer
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.saveUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
Summary
● JPA provides a standard API for managing relational data in Java applications.
● ORM frameworks, like Hibernate, implement JPA and offer additional features to
simplify database interactions.
● Setting up involves adding dependencies, configuring the database, defining
entities, and creating repository, service, and controller layers.
By leveraging JPA and ORM frameworks, you can efficiently manage relational data and
simplify database operations in your Java applications.
Repository interface
In Spring Boot and JPA, the repository interface is a central concept that allows you to
interact with your database entities. By extending Spring Data JPA’s repository interfaces,
you gain CRUD (Create, Read, Update, Delete) operations, pagination, and sorting
capabilities without having to write any boilerplate code.
Spring Data JPA provides several repository interfaces that you can extend based on your
needs:
Spring Data JPA provides a rich set of predefined methods in its repository interfaces, as
well as the ability to define custom queries. The core repository interface in Spring Data
JPA is JpaRepository, which provides the most comprehensive set of methods for CRUD
(Create, Read, Update, Delete) operations, pagination, and sorting.
1. Save
○ S save(S entity): Saves a given entity.
○ S saveAndFlush(S entity): Saves an entity and flushes changes instantly.
2. Find
○ Optional<T> findById(ID id): Retrieves an entity by its id.
○ boolean existsById(ID id): Checks if an entity with the given id exists.
○ List<T> findAll(): Retrieves all entities.
○ List<T> findAllById(Iterable<ID> ids): Retrieves all entities by their ids.
3. Delete
○ void deleteById(ID id): Deletes an entity by its id.
○ void delete(T entity): Deletes a given entity.
○ void deleteAll(Iterable<? extends T> entities): Deletes the given entities.
○ void deleteAll(): Deletes all entities.
In addition to the predefined methods, you can define custom query methods in your
repository interfaces using method naming conventions or the @Query annotation.
Spring Data JPA allows you to define query methods by simply declaring method names
that follow specific conventions.
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;
import java.util.List;
UserService
package com.example.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// Custom methods
public List<User> findUsersByName(String name) {
return userRepository.findByName(name);
}
Advanced Methods
JpaRepository
JpaRepository is a JPA (Java Persistence API) specific extension of Repository. It
contains the full API of CrudRepository and PagingAndSortingRepository. So it contains
API for basic CRUD operations and also API for pagination and sorting.
Syntax:
public interface JpaRepository<T,ID>
extends PagingAndSortingRepository<T,ID>, QueryByExampleExecutor<T>
Some of the most important methods that are available inside the JpaRepository are given
below
public interface DepartmentRepository extends CrudRepository<Department, Long> {}
Method : save(): Saves a given entity. Use the returned instance for further operations as
the save operation might have changed the entity instance completely.
Syntax:
<S extends T> S save(S entity)
● Parameters: entity – must not be null.
● Returns: the saved entity; will never be null.
● Throws: IllegalArgumentException – in case the given entity is null.
Method : getById(): Returns a reference to the entity with the given identifier.
Depending on how the JPA persistence provider is implemented this is very likely to
always return an instance and throw an EntityNotFoundException on first access. Some
of them will reject invalid identifiers immediately.
Syntax:
T getById(ID id)
Parameters: id – must not be null.
Return Type: a reference to the entity with the given identifier.
CRUD Repository
There is an interface available in Spring Boot named as CrudRepository that contains
methods for CRUD operations. It provides generic Crud operation on a repository. It is
defined in the package org.springframework.data.repository and It extends the Spring
Data Repository interface. If someone wants to use CrudRepository in the spring boot
application he/she has to create an interface and extend the CrudRepository interface.
Syntax:
public interface CrudRepository<T, ID> extends Repository<T, ID>
CrudRepository JpaRepository
It is a base interface and
It extends PagingAndSortingRepository that
extends Repository
extends CrudRepository.
Interface.
It doesn’t provide
methods for It provides all the methods for which are useful
implementing for implementing pagination.
pagination and sorting
To perform CRUD
operations, define To perform CRUD as well as batch operations,
repository extending define repository extends JpaRepository.
CrudRepository.
Syntax:
Syntax:
public interface
public interface JpaRepository<T,ID> extends
CrudRepository<T, ID>
PagingAndSortingRepository<T,ID>,
extends Repository<T,
QueryByExampleExecutor<T>
ID>
To retrieve all entities of a particular type, use the findAll() method provided by
JpaRepository.
b. Find by ID
To retrieve a single entity by its ID, use the findById(ID id) method, which returns
an Optional.
For more complex queries, use the @Query annotation with JPQL (Java Persistence
Query Language).
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;
You can also use native SQL queries with the @Query annotation.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;
Summary
1. Define Your Entity: Ensure you have a JPA entity that represents your data.
2. Create a Repository: Extend JpaRepository for basic CRUD operations.
3. Service Layer: Implement business logic and data retrieval using the repository.
4. Controller Layer: Expose service methods via RESTful endpoints.
5. Custom Queries and Pagination: Use custom queries, pagination, and sorting as
needed.
In Spring Boot, mapping a request body to an entity involves converting the JSON or
XML payload of an HTTP request into a Java object that represents the entity. This is
typically handled by Spring's data binding and Jackson (for JSON) or JAXB (for XML)
libraries.
When an HTTP request is made to this endpoint, Spring Boot performs the following
steps:
1. HTTP Request Parsing: Spring Boot receives the HTTP request and parses the
request body. This parsing is done using an HTTP message converter, which is
configured to handle the request payload type (JSON, XML, etc.).
2. Data Binding: Spring Boot uses the Jackson library (for JSON) or JAXB (for
XML) to bind the request body to the Java object. Jackson is the default JSON
processor in Spring Boot and is configured automatically.
3. Object Creation: A new instance of the entity (or DTO) is created, and the data
from the request body is populated into this instance. The JSON keys in the
request body correspond to the fields in the entity class.
Capture data from API requests
Capturing data from API requests in a Spring Boot application involves extracting data
from HTTP requests and processing it in your application. This can be done using various
methods, including request parameters, request bodies, and path variables. Here’s a guide
on how to capture and process data from API requests:
Request parameters are typically sent as query parameters in the URL. You can
capture them using the @RequestParam annotation in your controller.
Example Controller with Request Parameters
package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/greet")
public String greet(@RequestParam(name = "name", defaultValue = "Guest")
String name) {
return "Hello, " + name;
}
}
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/users/{userId}")
public String getUserById(@PathVariable("userId") Long userId) {
return "User ID: " + userId;
}
}
The request body contains data sent in the body of POST or PUT requests. You can
capture it using the @RequestBody annotation. This is often used to capture JSON
or XML data.
Example Controller with Request Body
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
private UserService userService;
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
}
Request Body:
json
{
"name": "John Doe",
"email": "john.doe@example.com"
}
Capture Headers
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/header")
public String getHeader(@RequestHeader("User-Agent") String userAgent) {
return "User-Agent: " + userAgent;
}
}
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/attribute")
public String getAttribute(HttpServletRequest request) {
Object myAttribute = request.getAttribute("myAttribute");
return "Attribute: " + (myAttribute != null ? myAttribute : "Not found");
}
}
Summary
In Spring Data JPA, you can build complex queries using various keywords and
techniques. These include method naming conventions, @Query annotations, and
the Criteria API. Here's a detailed guide on how to build complex queries using
these approaches:
I.Derived Query Methods:
Define queries by using method names. For example,
findByLastNameAndAgeGreaterThan can handle simple queries, but for more
complexity, this approach might not be enough.
Spring Data JPA allows you to define complex queries using method names in your
repository interfaces. The query derivation is based on the naming of the method.
Example Entity
package com.example.demo.entity;
import javax.persistence.*;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;
import java.util.List;
II.@Query Annotation:
Use the @Query annotation to define JPQL (Java Persistence Query Language) or
native SQL queries. This is useful for more complex queries that cannot be easily
expressed with method names.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;
You can also use native SQL queries with the @Query annotation.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;
}
III.Using JPA Criteria API
Build queries programmatically using CriteriaBuilder and CriteriaQuery for
dynamic conditions.
Using AND Condition: Retrieve all the persons whose age is >60 and living in the
city Delhi
@Service
public class PersonService {
@Autowired
private EntityManager entityManager;
query.where(finalPredicate);
TypedQuery<Person> typedQuery = entityManager.createQuery(query);
return typedQuery.getResultList();
}
}
Example
Assume you have a stored procedure in your database that performs some operations. For
example, in a MySQL database, you might have a stored procedure to get users by their
status:
DELIMITER $$
CREATE PROCEDURE GetUsersByStatus(IN userStatus VARCHAR(50))
BEGIN
SELECT * FROM users WHERE status = userStatus;
END$$
DELIMITER ;
You can use the @Procedure annotation in Spring Data JPA to call stored procedures.
Here's how you can define a repository method to call a stored procedure:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.data.jpa.repository.query.Procedure;
import java.util.List;
@Procedure(procedureName = "GetUsersByStatus")
List<User> getUsersByStatus(@Param("userStatus") String userStatus);
}
For more complex scenarios, you can use the @Query annotation with native queries.
This can also be used to call stored procedures.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Long> {
AND Condition:
To find persons who are over 30 years old and live in "New York":
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query("SELECT p FROM Person p WHERE p.age > :age AND p.city = :city")
List<Person> findByAgeGreaterThanAndCity(@Param("age") int age,
@Param("city") String city);
}
OR Condition:
To find persons who are either younger than 20 years old or live in "Los Angeles":
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {