├── .env
├── README.md
├── bezkoder-app
├── Dockerfile
├── README.md
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── bezkoder
│ └── spring
│ └── jpa
│ └── postgresql
│ ├── SpringBootJpaPostgresqlApplication.java
│ ├── controller
│ └── TutorialController.java
│ ├── model
│ └── Tutorial.java
│ └── repository
│ └── TutorialRepository.java
└── docker-compose.yml
/.env:
--------------------------------------------------------------------------------
1 | POSTGRESDB_USER=postgres
2 | POSTGRESDB_ROOT_PASSWORD=123456
3 | POSTGRESDB_DATABASE=bezkoder_db
4 | POSTGRESDB_LOCAL_PORT=5433
5 | POSTGRESDB_DOCKER_PORT=5432
6 |
7 | SPRING_LOCAL_PORT=6868
8 | SPRING_DOCKER_PORT=8080
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Docker Compose Spring Boot and Postgres example
2 |
3 | ## Run the System
4 | We can easily run the whole with only a single command:
5 | ```bash
6 | docker compose up
7 | ```
8 |
9 | Docker will pull the PostgreSQL and Spring Boot images (if our machine does not have it before).
10 |
11 | The services can be run on the background with command:
12 | ```bash
13 | docker compose up -d
14 | ```
15 |
16 | ## Stop the System
17 | Stopping all the running containers is also simple with a single command:
18 | ```bash
19 | docker compose down
20 | ```
21 |
22 | If you need to stop and remove all containers, networks, and all images used by any service in docker-compose.yml file, use the command:
23 | ```bash
24 | docker compose down --rmi all
25 | ```
26 |
27 | For more detail, please visit:
28 | > [Docker Compose Spring Boot and Postgres](https://www.bezkoder.com/docker-compose-spring-boot-postgres/)
29 |
30 | Related Posts:
31 | > [Spring Boot + PostgreSQL: CRUD Rest API example](https://www.bezkoder.com/spring-boot-postgresql-example/)
32 |
33 | > [Spring Boot R2DBC + PostgreSQL example](https://www.bezkoder.com/spring-boot-r2dbc-postgresql/)
34 |
35 | > [Spring Boot Validate Request Body](https://www.bezkoder.com/spring-boot-validate-request-body/)
36 |
37 | > [Spring Boot and Swagger 3 example](https://www.bezkoder.com/spring-boot-swagger-3/)
38 |
39 | > [Spring Boot Redis Cache example](https://www.bezkoder.com/spring-boot-redis-cache-example/)
40 |
41 | > [Spring Boot File upload example](https://www.bezkoder.com/spring-boot-file-upload/)
42 |
43 | > [Exception handling: @RestControllerAdvice example in Spring Boot](https://www.bezkoder.com/spring-boot-restcontrolleradvice/)
44 |
45 | > [Spring Boot Repository Unit Test with @DataJpaTest](https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/)
46 |
47 | > [Spring Boot Rest Controller Unit Test with @WebMvcTest](https://www.bezkoder.com/spring-boot-webmvctest/)
48 |
49 | Security:
50 | > [Secure Spring Boot App with Spring Security & JWT Authentication (PostgreSQL)](https://www.bezkoder.com/spring-boot-security-postgresql-jwt-authentication/)
51 |
--------------------------------------------------------------------------------
/bezkoder-app/Dockerfile:
--------------------------------------------------------------------------------
1 | # FROM maven:3.8.2-jdk-8 # for Java 8
2 | FROM maven:3.8.5-openjdk-17
3 |
4 | WORKDIR /bezkoder-app
5 | COPY . .
6 | RUN mvn clean install
7 |
8 | CMD mvn spring-boot:run
--------------------------------------------------------------------------------
/bezkoder-app/README.md:
--------------------------------------------------------------------------------
1 | # Spring Boot JPA PostgreSQL example with Maven
2 |
3 | For instruction, please visit:
4 | > [Spring Boot PostgreSQL with Maven example using Spring Data JPA](https://www.bezkoder.com/spring-boot-postgresql-example/)
5 |
6 | Front-end that works well with this Back-end
7 | > [Angular 8](https://www.bezkoder.com/angular-crud-app/) / [Angular 10](https://www.bezkoder.com/angular-10-crud-app/) / [Angular 11](https://www.bezkoder.com/angular-11-crud-app/) / [Angular 12](https://www.bezkoder.com/angular-12-crud-app/) / [Angular 13](https://www.bezkoder.com/angular-13-crud-example/) / [Angular 14](https://www.bezkoder.com/angular-14-crud-example/) / [Angular 15](https://www.bezkoder.com/angular-15-crud-example/) / [Angular 16 Client](https://www.bezkoder.com/angular-16-crud-example/)
8 |
9 | > [Vue 2](https://www.bezkoder.com/vue-js-crud-app/) / [Vue 3](https://www.bezkoder.com/vue-3-crud/) / [Vuetify Client](https://www.bezkoder.com/vuetify-data-table-example/)
10 |
11 | > [React](https://www.bezkoder.com/react-crud-web-api/) / [React Redux Client](https://www.bezkoder.com/react-redux-crud-example/)
12 |
13 | More practice:
14 | > [Spring Boot Validate Request Body](https://www.bezkoder.com/spring-boot-validate-request-body/)
15 |
16 | > [Spring Boot File upload example with Multipart File](https://www.bezkoder.com/spring-boot-file-upload/)
17 |
18 | > [Spring Boot Pagination & Filter example | Spring JPA, Pageable](https://www.bezkoder.com/spring-boot-pagination-filter-jpa-pageable/)
19 |
20 | > [Spring Data JPA Sort/Order by multiple Columns | Spring Boot](https://www.bezkoder.com/spring-data-sort-multiple-columns/)
21 |
22 | > [Spring Boot Repository Unit Test with @DataJpaTest](https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/)
23 |
24 | > [Spring Boot Rest Controller Unit Test with @WebMvcTest](https://www.bezkoder.com/spring-boot-webmvctest/)
25 |
26 | > Cache the result: [Spring Boot Redis Cache example](https://www.bezkoder.com/spring-boot-redis-cache-example/)
27 |
28 | > Documentation: [Spring Boot with Swagger 3 example](https://www.bezkoder.com/spring-boot-swagger-3/)
29 |
30 | > Reactive Rest API: [Spring Boot WebFlux example](https://www.bezkoder.com/spring-boot-webflux-rest-api/)
31 |
32 | > [Deploy Spring Boot App on AWS – Elastic Beanstalk](https://www.bezkoder.com/deploy-spring-boot-aws-eb/)
33 |
34 | Associations:
35 | > [Spring Boot One To One example with Spring JPA, Hibernate](https://www.bezkoder.com/jpa-one-to-one/)
36 |
37 | > [Spring Boot One To Many example with Spring JPA, Hibernate](https://www.bezkoder.com/jpa-one-to-many/)
38 |
39 | > [Spring Boot Many To Many example with Spring JPA, Hibernate](https://www.bezkoder.com/jpa-many-to-many/)
40 |
41 | Security:
42 | > [Spring Boot, Spring Security, PostgreSQL: JWT Authentication & Authorization example](https://www.bezkoder.com/spring-boot-security-postgresql-jwt-authentication/)
43 |
44 | Exception Handling:
45 | > [Spring Boot @ControllerAdvice & @ExceptionHandler example](https://www.bezkoder.com/spring-boot-controlleradvice-exceptionhandler/)
46 |
47 | > [@RestControllerAdvice example in Spring Boot](https://www.bezkoder.com/spring-boot-restcontrolleradvice/)
48 |
49 | Fullstack:
50 | > [Vue.js + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-vue-js-postgresql/)
51 |
52 | > [Angular 10 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/angular-10-spring-boot-postgresql/)
53 |
54 | > [Angular 11 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/angular-11-spring-boot-postgresql/)
55 |
56 | > [Angular 12 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/angular-12-spring-boot-postgresql/)
57 |
58 | > [Angular 13 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-13-postgresql/)
59 |
60 | > [Angular 14 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-14-postgresql/)
61 |
62 | > [Angular 15 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-15-postgresql/)
63 |
64 | > [Angular 16 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-16-postgresql/)
65 |
66 | > [React + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-react-postgresql/)
67 |
68 | Run both Back-end & Front-end in one place:
69 | > [Integrate Angular with Spring Boot Rest API](https://www.bezkoder.com/integrate-angular-spring-boot/)
70 |
71 | > [Integrate React.js with Spring Boot Rest API](https://www.bezkoder.com/integrate-reactjs-spring-boot/)
72 |
73 | > [Integrate Vue.js with Spring Boot Rest API](https://www.bezkoder.com/integrate-vue-spring-boot/)
74 |
75 | ## Run Spring Boot application
76 | ```
77 | mvn spring-boot:run
78 | ```
79 |
80 |
--------------------------------------------------------------------------------
/bezkoder-app/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.1.0
9 |
10 |
11 | com.bezkoder
12 | spring-boot-jpa-postgresql
13 | 0.0.1-SNAPSHOT
14 | spring-boot-jpa-postgresql
15 | Spring Boot, PostgreSQL example with Maven, Spring JPA
16 |
17 |
18 | 17
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-data-jpa
25 |
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-web
30 |
31 |
32 |
33 | org.postgresql
34 | postgresql
35 | runtime
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 | org.junit.vintage
44 | junit-vintage-engine
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-maven-plugin
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/bezkoder-app/src/main/java/com/bezkoder/spring/jpa/postgresql/SpringBootJpaPostgresqlApplication.java:
--------------------------------------------------------------------------------
1 | package com.bezkoder.spring.jpa.postgresql;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class SpringBootJpaPostgresqlApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(SpringBootJpaPostgresqlApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/bezkoder-app/src/main/java/com/bezkoder/spring/jpa/postgresql/controller/TutorialController.java:
--------------------------------------------------------------------------------
1 | package com.bezkoder.spring.jpa.postgresql.controller;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Optional;
6 |
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.CrossOrigin;
11 | import org.springframework.web.bind.annotation.DeleteMapping;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PathVariable;
14 | import org.springframework.web.bind.annotation.PostMapping;
15 | import org.springframework.web.bind.annotation.PutMapping;
16 | import org.springframework.web.bind.annotation.RequestBody;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 | import org.springframework.web.bind.annotation.RequestParam;
19 | import org.springframework.web.bind.annotation.RestController;
20 |
21 | import com.bezkoder.spring.jpa.postgresql.model.Tutorial;
22 | import com.bezkoder.spring.jpa.postgresql.repository.TutorialRepository;
23 |
24 | @CrossOrigin(origins = "http://localhost:8081")
25 | @RestController
26 | @RequestMapping("/api")
27 | public class TutorialController {
28 |
29 | @Autowired
30 | TutorialRepository tutorialRepository;
31 |
32 | @GetMapping("/tutorials")
33 | public ResponseEntity> getAllTutorials(@RequestParam(required = false) String title) {
34 | try {
35 | List tutorials = new ArrayList();
36 |
37 | if (title == null)
38 | tutorialRepository.findAll().forEach(tutorials::add);
39 | else
40 | tutorialRepository.findByTitleContaining(title).forEach(tutorials::add);
41 |
42 | if (tutorials.isEmpty()) {
43 | return new ResponseEntity<>(HttpStatus.NO_CONTENT);
44 | }
45 |
46 | return new ResponseEntity<>(tutorials, HttpStatus.OK);
47 | } catch (Exception e) {
48 | return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
49 | }
50 | }
51 |
52 | @GetMapping("/tutorials/{id}")
53 | public ResponseEntity getTutorialById(@PathVariable("id") long id) {
54 | Optional tutorialData = tutorialRepository.findById(id);
55 |
56 | if (tutorialData.isPresent()) {
57 | return new ResponseEntity<>(tutorialData.get(), HttpStatus.OK);
58 | } else {
59 | return new ResponseEntity<>(HttpStatus.NOT_FOUND);
60 | }
61 | }
62 |
63 | @PostMapping("/tutorials")
64 | public ResponseEntity createTutorial(@RequestBody Tutorial tutorial) {
65 | try {
66 | Tutorial _tutorial = tutorialRepository
67 | .save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false));
68 | return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
69 | } catch (Exception e) {
70 | return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
71 | }
72 | }
73 |
74 | @PutMapping("/tutorials/{id}")
75 | public ResponseEntity updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
76 | Optional tutorialData = tutorialRepository.findById(id);
77 |
78 | if (tutorialData.isPresent()) {
79 | Tutorial _tutorial = tutorialData.get();
80 | _tutorial.setTitle(tutorial.getTitle());
81 | _tutorial.setDescription(tutorial.getDescription());
82 | _tutorial.setPublished(tutorial.isPublished());
83 | return new ResponseEntity<>(tutorialRepository.save(_tutorial), HttpStatus.OK);
84 | } else {
85 | return new ResponseEntity<>(HttpStatus.NOT_FOUND);
86 | }
87 | }
88 |
89 | @DeleteMapping("/tutorials/{id}")
90 | public ResponseEntity deleteTutorial(@PathVariable("id") long id) {
91 | try {
92 | tutorialRepository.deleteById(id);
93 | return new ResponseEntity<>(HttpStatus.NO_CONTENT);
94 | } catch (Exception e) {
95 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
96 | }
97 | }
98 |
99 | @DeleteMapping("/tutorials")
100 | public ResponseEntity deleteAllTutorials() {
101 | try {
102 | tutorialRepository.deleteAll();
103 | return new ResponseEntity<>(HttpStatus.NO_CONTENT);
104 | } catch (Exception e) {
105 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
106 | }
107 |
108 | }
109 |
110 | @GetMapping("/tutorials/published")
111 | public ResponseEntity> findByPublished() {
112 | try {
113 | List tutorials = tutorialRepository.findByPublished(true);
114 |
115 | if (tutorials.isEmpty()) {
116 | return new ResponseEntity<>(HttpStatus.NO_CONTENT);
117 | }
118 | return new ResponseEntity<>(tutorials, HttpStatus.OK);
119 | } catch (Exception e) {
120 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
121 | }
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/bezkoder-app/src/main/java/com/bezkoder/spring/jpa/postgresql/model/Tutorial.java:
--------------------------------------------------------------------------------
1 | package com.bezkoder.spring.jpa.postgresql.model;
2 |
3 | import jakarta.persistence.*;
4 |
5 | @Entity
6 | @Table(name = "tutorials")
7 | public class Tutorial {
8 |
9 | @Id
10 | @GeneratedValue(strategy = GenerationType.AUTO)
11 | private long id;
12 |
13 | @Column(name = "title")
14 | private String title;
15 |
16 | @Column(name = "description")
17 | private String description;
18 |
19 | @Column(name = "published")
20 | private boolean published;
21 |
22 | public Tutorial() {
23 |
24 | }
25 |
26 | public Tutorial(String title, String description, boolean published) {
27 | this.title = title;
28 | this.description = description;
29 | this.published = published;
30 | }
31 |
32 | public long getId() {
33 | return id;
34 | }
35 |
36 | public String getTitle() {
37 | return title;
38 | }
39 |
40 | public void setTitle(String title) {
41 | this.title = title;
42 | }
43 |
44 | public String getDescription() {
45 | return description;
46 | }
47 |
48 | public void setDescription(String description) {
49 | this.description = description;
50 | }
51 |
52 | public boolean isPublished() {
53 | return published;
54 | }
55 |
56 | public void setPublished(boolean isPublished) {
57 | this.published = isPublished;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/bezkoder-app/src/main/java/com/bezkoder/spring/jpa/postgresql/repository/TutorialRepository.java:
--------------------------------------------------------------------------------
1 | package com.bezkoder.spring.jpa.postgresql.repository;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | import com.bezkoder.spring.jpa.postgresql.model.Tutorial;
8 |
9 | public interface TutorialRepository extends JpaRepository {
10 | List findByPublished(boolean published);
11 |
12 | List findByTitleContaining(String title);
13 | }
14 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | postgresdb:
5 | image: postgres
6 | restart: unless-stopped
7 | env_file: ./.env
8 | environment:
9 | - POSTGRES_USER=$POSTGRESDB_USER
10 | - POSTGRES_PASSWORD=$POSTGRESDB_ROOT_PASSWORD
11 | - POSTGRES_DB=$POSTGRESDB_DATABASE
12 | ports:
13 | - $POSTGRESDB_LOCAL_PORT:$POSTGRESDB_DOCKER_PORT
14 | volumes:
15 | - db:/var/lib/postgres
16 | app:
17 | depends_on:
18 | - postgresdb
19 | build: ./bezkoder-app
20 | restart: on-failure
21 | env_file: ./.env
22 | ports:
23 | - $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT
24 | environment:
25 | SPRING_APPLICATION_JSON: '{
26 | "spring.datasource.url" : "jdbc:postgresql://postgresdb:$POSTGRESDB_DOCKER_PORT/$POSTGRESDB_DATABASE",
27 | "spring.datasource.username" : "$POSTGRESDB_USER",
28 | "spring.datasource.password" : "$POSTGRESDB_ROOT_PASSWORD",
29 | "spring.jpa.properties.hibernate.dialect" : "org.hibernate.dialect.PostgreSQLDialect",
30 | "spring.jpa.hibernate.ddl-auto" : "update"
31 | }'
32 | volumes:
33 | - .m2:/root/.m2
34 | stdin_open: true
35 | tty: true
36 |
37 | volumes:
38 | db:
39 |
--------------------------------------------------------------------------------