Here’s a step-by-step example of a CRUD (Create, Read, Update, Delete) operation using Java Spring Boot with PostgreSQL, updated for 2025 best practices.
✅ Tools & Technologies:
- Java 17+ (LTS)
- Spring Boot 3.2+
- Spring Data JPA
- PostgreSQL 15+
- Maven or Gradle
- Postman (for testing API) or Apidog Fast Request - HTTP REST Client
- IntelliJ or VSCode
🔧 Step 1: Create a Spring Boot Project
Use Spring Initializr:
- Project: Maven
- Language: Java
- Spring Boot: 3.2.x
- Dependencies: -Spring Web -Spring Data JPA -PostgreSQL Driver -Spring Boot DevTools
Generate and unzip the project.
🗂️ Step 2: Configure application.properties
In src/main/resources/application.properties:
spring.application.name=java-crud-postgre-sql
spring.datasource.url=jdbc:postgresql://localhost:5432/database_name
spring.datasource.username=DB user name
spring.datasource.password=DB password here
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
server.port=8080
Ensure the PostgreSQL server is running and the database database_name exists.
🧱 Step 3: Create an Entity Class
package com.example.demo.model;
import jakarta.persistence.*;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double price;
// Getters and Setters
}
📦 Step 4: Create a Repository
package com.example.demo.repository;
import com.example.demo.model.Product;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository {
}
⚙️ Step 5: Create a Service Layer (Optional but Best Practice)
package com.example.demo.service;
import com.example.demo.model.Product;
import com.example.demo.repository.ProductRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class ProductService {
private final ProductRepository repo;
public ProductService(ProductRepository repo) {
this.repo = repo;
}
public List getAll() {
return repo.findAll();
}
public Product save(Product product) {
return repo.save(product);
}
public Optional getById(Long id) {
return repo.findById(id);
}
public void deleteById(Long id) {
repo.deleteById(id);
}
public Product update(Long id, Product updatedProduct) {
return repo.findById(id).map(product -> {
product.setName(updatedProduct.getName());
product.setPrice(updatedProduct.getPrice());
return repo.save(product);
}).orElseThrow(() -> new RuntimeException("Product not found"));
}
}
🌐 Step 6: Create a REST Controller
package com.example.demo.controller;
import com.example.demo.model.Product;
import com.example.demo.service.ProductService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService service;
public ProductController(ProductService service) {
this.service = service;
}
@GetMapping
public List getAll() {
return service.getAll();
}
@GetMapping("/{id}")
public ResponseEntity getById(@PathVariable Long id) {
return service.getById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public Product create(@RequestBody Product product) {
return service.save(product);
}
@PutMapping("/{id}")
public Product update(@PathVariable Long id, @RequestBody Product product) {
return service.update(id, product);
}
@DeleteMapping("/{id}")
public ResponseEntity delete(@PathVariable Long id) {
service.deleteById(id);
return ResponseEntity.noContent().build();
}
}
🧪 Step 7: Test with Postman or curl
POST /api/products – Create
GET /api/products – Read all
GET /api/products/{id} – Read one
PUT /api/products/{id} – Update
DELETE /api/products/{id} – Delete
GitHub repo: https://github.com/saifcse06/java-crud-postgre-sql/
If you have any doubts or suggestions, let me know in the comments section. Happy coding!