How to make APIs with Spring Boot: read from a MySQL database

Search for a command to run...

No comments yet. Be the first to comment.
Concurrency and Parallelism in Golang

Patterns are everywhere This great comic is from False Knees and it illustrates that you can find patterns everywhere, you can also check out this National Graphic article. Your code base is no different. The objective of this article is to understa...

Intro There's an xkcd for everything! If you are preparing for interviews or just studying DSA you will eventually reach graph problems and then dynamic programming. This post is the step before recursion, we are going to see how BFS and DFS algorit...

organize your containers with Docker Compose and use CURL to make requests

It's alive BUT There are huge codebases of RoR from famous companies such as Github, Gitlab, Airbnb, Shopify, Groupon and even Twitch that are still using it. However the ecosystem is definitely in decline and companies are struggling to recruit seni...


For any questions you can ask me on Twitter @ tekbog
In my case I'm gonna use MySQL Workbench to create a database called "mydb" and then add a table called "my_table"

Once that's done run this query to put some data in your database:
USE mydb;
CREATE TABLE my_table
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL
);
INSERT INTO my_table (name, email) VALUES ("random_name", "random@random.com");
INSERT INTO my_table (name, email) VALUES ("random_name1", "random1@random.com");
INSERT INTO my_table (name, email) VALUES ("random_name2", "random2@random.com");
Connect your database to the Spring Boot app by changing
application.properties

The port is default, make sure it's the same. You can check the port number when you start the Spring Boot app.
The username and password pertain to your MySQL database.
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
And the dependencies are:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
You can use Spring Initializr as well to set up your project, it's highly recommended.
In order to make calls to the server I'm going to be using Postman Although there are many alternatives.
The "folders" are called packages, once you create them: inside you can make classes, interfaces, etc.
UserData class makes it possible to interact with the database
package com.example.sqldbexample.entity;
import lombok.Getter;
import javax.persistence.*;
//lombok getter so we don't have to write getters
@Getter
//The entity interacts with the database
@Entity
@Table(name = "my_table")
public class UserData {
//an id is always needed to index the data
//the annotation GeneratedValue allows the data to be generated automatically
//and we add the name of the columns where the data goes
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
}
To begin we import Lombok so we don't have to write the getters for the class. Afterwards we define the class as Entity and map the Java objects to the database we are accessing. The most confused annotation could be GeneratedValue: we always need an id and in this case we made our id to be generated automatically. Spring annotations have the following syntax:
@AnnotationName(parameter="parameter value")
The Repository interface is a DAO (data access object) bean that simplifies our interaction with SQL thanks to JPA, the interface takes 2 parameters: the type of object and the type of id, after which it will allow you to use its extended methods:

In our case we want to interact with the entity object we have created called UserData and the id is Long type.
Note that Repository annotation also indicates that this is a type of bean we can use anywhere in our project.
package com.example.sqldbexample.repository;
import com.example.sqldbexample.entity.UserData;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
//repository to interact with the entity
//we use the JpaRepository because of all its methods
@Repository
public interface UserDataRepository extends JpaRepository<UserData, Long> {
}
UserDataService interface is gonna allow us to use the repository we have just created to get the data we want
package com.example.sqldbexample.service;
import com.example.sqldbexample.entity.UserData;
import java.util.List;
//interface to handle the entity UserData
public interface UserDataService {
List<UserData> getUserData();
}
Now the implementation is as follows:
package com.example.sqldbexample.service;
import com.example.sqldbexample.entity.UserData;
import com.example.sqldbexample.repository.UserDataRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserDataServiceImpl implements UserDataService{
//get the repository bean
@Autowired
UserDataRepository userDataRepository;
//we use the repository bean to get access to all the methods
//like findAll
@Override
public List<UserData> getUserData() {
return userDataRepository.findAll();
}
}
Thanks to the JPA repository we get access to all its methods without having to implement any of them, it just works with our MySQL database. So in order to get all the users from the table we use .findAll() method.
You can read my previous article if you are unfamiliar with the Controller
//@RestController annotation will make this class the controller
//meaning that it's listening to htttp://localhost:8080 calls
//and replying with whatever endpoints you have made
@RestController
//localhost:8080/api/v1
@RequestMapping("api/v1")
public class Controller {
@Autowired
private UserDataService userDataService;
@GetMapping("/getdata")
public List<UserData> getData(){
return userDataService.getUserData();
}
}
The main difference is the fact that we add RequestMapping so everything goes to api/v1 path after localhost:port/. Putting the version of your API is good practice.
To sum it up we use the UserDataService bean (service), the Autowired annotation allows us to get the bean through Inversion of Control (Spring magic) and use that interface's implementation without calling it ourselves.
Start the server, make sure your database is running and then using Postman call localhost:8080/api/v1/getdata
you should get this back:
