├── .env ├── README.md ├── bezkoder-app ├── Dockerfile ├── README.md ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── bezkoder │ └── spring │ └── datajpa │ ├── SpringBootDataJpaApplication.java │ ├── controller │ └── TutorialController.java │ ├── model │ └── Tutorial.java │ └── repository │ └── TutorialRepository.java └── docker-compose.yml /.env: -------------------------------------------------------------------------------- 1 | MYSQLDB_USER=root 2 | MYSQLDB_ROOT_PASSWORD=123456 3 | MYSQLDB_DATABASE=bezkoder_db 4 | MYSQLDB_LOCAL_PORT=3307 5 | MYSQLDB_DOCKER_PORT=3306 6 | 7 | SPRING_LOCAL_PORT=6868 8 | SPRING_DOCKER_PORT=8080 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Compose Spring Boot and MySQL 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 MySQL 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 MySQL example](https://www.bezkoder.com/docker-compose-spring-boot-mysql/) 29 | 30 | Related Posts: 31 | > [Spring Boot JPA + MySQL - Building Rest CRUD API example](https://www.bezkoder.com/spring-boot-jpa-crud-rest-api/) 32 | 33 | > [Spring Boot R2DBC + MySQL example](https://www.bezkoder.com/spring-r2dbc-mysql/) 34 | 35 | > [Spring Boot + GraphQL + MySQL example](https://www.bezkoder.com/spring-boot-graphql-mysql-jpa/) 36 | 37 | > [Spring Boot Rest XML example – Web service with XML Response](https://www.bezkoder.com/spring-boot-rest-xml/) 38 | 39 | > [Spring Boot: Upload CSV file data into MySQL Database](https://www.bezkoder.com/spring-boot-upload-csv-file/) 40 | 41 | > [Spring Boot: Upload Excel file data into MySQL Database](https://www.bezkoder.com/spring-boot-upload-excel-file-database/) 42 | 43 | > [Spring Boot Validate Request Body](https://www.bezkoder.com/spring-boot-validate-request-body/) 44 | 45 | > [Spring Boot and Swagger 3 example](https://www.bezkoder.com/spring-boot-swagger-3/) 46 | 47 | > [Spring Boot Redis Cache example](https://www.bezkoder.com/spring-boot-redis-cache-example/) 48 | 49 | > [Spring Boot File upload example](https://www.bezkoder.com/spring-boot-file-upload/) 50 | 51 | > [Exception handling: @RestControllerAdvice example in Spring Boot](https://www.bezkoder.com/spring-boot-restcontrolleradvice/) 52 | 53 | > [Spring Boot Repository Unit Test with @DataJpaTest](https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/) 54 | 55 | > [Spring Boot Rest Controller Unit Test with @WebMvcTest](https://www.bezkoder.com/spring-boot-webmvctest/) 56 | 57 | > [Deploy Spring Boot App on AWS – Elastic Beanstalk](https://www.bezkoder.com/deploy-spring-boot-aws-eb/) 58 | 59 | Security: 60 | > [Spring Boot + Spring Security JWT Authentication & Authorization](https://www.bezkoder.com/spring-boot-jwt-authentication/) 61 | -------------------------------------------------------------------------------- /bezkoder-app/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM maven:3.8.5-openjdk-17 # for Java 17 2 | FROM maven:3.8.2-jdk-8 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 MySQL - Building Rest CRUD API example 2 | 3 | For more detail, please visit: 4 | > [Spring Boot JPA + MySQL - Building Rest CRUD API example](https://www.bezkoder.com/spring-boot-jpa-crud-rest-api/) 5 | 6 | > [Spring Boot JPA + PostgreSQL - Building Rest CRUD API example](https://www.bezkoder.com/spring-boot-postgresql-example/) 7 | 8 | More Practice: 9 | > [Spring Boot File upload example with Multipart File](https://www.bezkoder.com/spring-boot-file-upload/) 10 | 11 | > [Spring Boot Pagination & Filter example | Spring JPA, Pageable](https://www.bezkoder.com/spring-boot-pagination-filter-jpa-pageable/) 12 | 13 | > [Spring Data JPA Sort/Order by multiple Columns | Spring Boot](https://www.bezkoder.com/spring-data-sort-multiple-columns/) 14 | 15 | > [Spring Boot Repository Unit Test with @DataJpaTest](https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/) 16 | 17 | > [Deploy Spring Boot App on AWS – Elastic Beanstalk](https://www.bezkoder.com/deploy-spring-boot-aws-eb/) 18 | 19 | Security: 20 | > [Spring Boot + Spring Security JWT Authentication & Authorization](https://www.bezkoder.com/spring-boot-jwt-authentication/) 21 | 22 | Fullstack: 23 | > [Vue.js + Spring Boot + MySQL example](https://bezkoder.com/spring-boot-vue-js-mysql/) 24 | 25 | > [Angular 10 + Spring Boot + MySQL example](https://www.bezkoder.com/angular-10-spring-boot-crud/) 26 | 27 | > [Angular 11 + Spring Boot + MySQL example](https://www.bezkoder.com/angular-11-spring-boot-crud/) 28 | 29 | > [Angular 12 + Spring Boot + MySQL example](https://bezkoder.com/angular-12-spring-boot-mysql/) 30 | 31 | > [Angular 13 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-13-mysql/) 32 | 33 | > [Angular 14 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-14-mysql/) 34 | 35 | > [Angular 15 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-15-mysql/) 36 | 37 | > [Angular 16 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-16-mysql/) 38 | 39 | > [React + Spring Boot + MySQL example](https://www.bezkoder.com/react-spring-boot-crud/) 40 | 41 | Run both Back-end & Front-end in one place: 42 | > [Integrate Angular with Spring Boot Rest API](https://www.bezkoder.com/integrate-angular-spring-boot/) 43 | 44 | > [Integrate React.js with Spring Boot Rest API](https://www.bezkoder.com/integrate-reactjs-spring-boot/) 45 | 46 | > [Integrate Vue.js with Spring Boot Rest API](https://www.bezkoder.com/integrate-vue-spring-boot/) 47 | 48 | ## Run Spring Boot application 49 | ``` 50 | mvn spring-boot:run 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /bezkoder-app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.1.RELEASE 9 | 10 | 11 | com.bezkoder 12 | spring-boot-data-jpa 13 | 0.0.1-SNAPSHOT 14 | spring-boot-data-jpa 15 | Demo project for Spring Boot Apis CRUD using Spring Data JPA 16 | 17 | 18 | 1.8 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 | mysql 34 | mysql-connector-java 35 | runtime 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | org.junit.vintage 45 | junit-vintage-engine 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-maven-plugin 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /bezkoder-app/src/main/java/com/bezkoder/spring/datajpa/SpringBootDataJpaApplication.java: -------------------------------------------------------------------------------- 1 | package com.bezkoder.spring.datajpa; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootDataJpaApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootDataJpaApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /bezkoder-app/src/main/java/com/bezkoder/spring/datajpa/controller/TutorialController.java: -------------------------------------------------------------------------------- 1 | package com.bezkoder.spring.datajpa.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.datajpa.model.Tutorial; 22 | import com.bezkoder.spring.datajpa.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/datajpa/model/Tutorial.java: -------------------------------------------------------------------------------- 1 | package com.bezkoder.spring.datajpa.model; 2 | 3 | import javax.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/datajpa/repository/TutorialRepository.java: -------------------------------------------------------------------------------- 1 | package com.bezkoder.spring.datajpa.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import com.bezkoder.spring.datajpa.model.Tutorial; 8 | 9 | public interface TutorialRepository extends JpaRepository { 10 | List findByPublished(boolean published); 11 | List findByTitleContaining(String title); 12 | } 13 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | mysqldb: 5 | image: mysql:5.7 6 | restart: unless-stopped 7 | env_file: ./.env 8 | environment: 9 | - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD 10 | - MYSQL_DATABASE=$MYSQLDB_DATABASE 11 | ports: 12 | - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT 13 | volumes: 14 | - db:/var/lib/mysql 15 | app: 16 | depends_on: 17 | - mysqldb 18 | build: ./bezkoder-app 19 | restart: on-failure 20 | env_file: ./.env 21 | ports: 22 | - $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT 23 | environment: 24 | SPRING_APPLICATION_JSON: '{ 25 | "spring.datasource.url" : "jdbc:mysql://mysqldb:$MYSQLDB_DOCKER_PORT/$MYSQLDB_DATABASE?useSSL=false", 26 | "spring.datasource.username" : "$MYSQLDB_USER", 27 | "spring.datasource.password" : "$MYSQLDB_ROOT_PASSWORD", 28 | "spring.jpa.properties.hibernate.dialect" : "org.hibernate.dialect.MySQL5InnoDBDialect", 29 | "spring.jpa.hibernate.ddl-auto" : "update" 30 | }' 31 | volumes: 32 | - .m2:/root/.m2 33 | stdin_open: true 34 | tty: true 35 | 36 | volumes: 37 | db: 38 | --------------------------------------------------------------------------------