├── .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 | --------------------------------------------------------------------------------