September 17, 2022

Spring Boot + Spring Data JPA + MySQL + Spring RESTful

In this tutorial we’ll see how to create Spring Boot + Spring Data JPA + MySQL + Spring RESTful Webservice. There is already a similar example in the post Spring Data JPA Example. By using Spring Boot you will see a significant reduction in required configuration.

If you want to see how to create Maven project, please check this post- Create Java Project Using Maven in Eclipse

Maven Dependencies

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.knpcode</groupId>
  <artifactId>SpringBootProject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
  </parent>
  <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-web</artifactId>
    </dependency>
    <!-- MySQL Driver -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

In our configuration, Spring Boot version is 2.1.6 so Spring Boot gets the dependencies which support this version.

For Spring Data JPA you need to add spring-boot-starter-data-jpa that will get Spring Data, Hibernate and other jars required for JPA.

Since we are developing a web service, we add a spring-boot-starter-web dependency, that adds the necessary dependencies required for creating a Spring web application.

spring-boot-maven-plugin is also added, this plugin provides many convenient features-

  • It helps to create an executable jar (über-jar), which makes it more convenient to execute and transport your service.
  • It also searches for the public static void main() method to flag the class having this method as a runnable class.

With these dependencies added Spring Boot takes care of getting the required jar dependencies, even an embedded web server (Tomcat in this case) because of the starter web dependency.

DB table Query

MySQL DB table used for this Spring Boot and Spring data JPA example can be created using the following query.

CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) DEFAULT NULL,
  `last_name` varchar(45) DEFAULT NULL,
  `department` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

JPA Entity class

Entity class which maps to the employee table in DB.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="employee")
public class Employee {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;
  @Column(name="first_name")
  private String firstName;
  @Column(name="last_name")
  private String lastName;
  @Column(name="department")
  private String dept;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getDept() {
    return dept;
  }
  public void setDept(String dept) {
    this.dept = dept;
  }

  @Override
  public String toString() {
    return "Id= " + getId() + " First Name= " + 
           getFirstName() + " Last Name= " + getLastName() + 
           " Dept= "+ getDept();
  }
}

@Entity annotation specifies that this model class is an entity.

@Table annotation specifies the primary table for the entity.

@Id annotation specifies the primary key of the entity.

@GeneratedValue specifies the primary key generation strategy which is autoincrement in this case.

@Column annotation specifies the mapped table column name for the field.

Spring Data JPA Repository Class

import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.knpcode.springbootproject.model.Employee;

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {	
  List<Employee> findByLastName(String lastName);
}

EmployeeRepository interface extends CrudRepository which takes the domain class to manage (Employee in this case) as well as the id type of the domain class as type arguments.

That is all the data access code you need for your CRUD functionality, no need to write a class that implements this interface. Spring takes care of automatically implementing this repository interface.

Apart from the methods inherited from CrudRepository there is one more method findByLastName added in the Repository. Custom queries can be generated automatically or you can write the query as Named query or by using @Query annotation with in the repository.

To see an example of @Query annotation, check this post- Spring Data JPA @Query Annotation Example

To see an example of @NamedQuery annotation, check this post- Spring Data JPA @NamedQuery Annotation Example

Service class

From the service layer we’ll call the DAO layer methods. Since all we need is a repository in case of spring data so we’ll call methods of repository from the service class. Notice that repository instance has to be injected in the service class.

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.knpcode.springbootproject.model.Employee;
import com.knpcode.springbootproject.repository.EmployeeRepository;

@Service
public class EmployeeService {
  @Autowired
  private EmployeeRepository repository;

  public Employee getEmployeeById(int id) {
    return repository.findById(id).get();
  }

  public List<Employee> getAllEmployees(){
    return (List<Employee>) repository.findAll();
  }

  public void deleteEmployeeById(int id){
    repository.deleteById(id);
  }

  public Employee addEmployee(Employee emp) {
    return repository.save(emp);
  }

  public List<Employee> getEmployeeByLastName(String lastName) {
    return repository.findByLastName(lastName);
  }
}

Controller class

Using a Rest controller class we’ll map the path to the methods that are to be called for the requests.

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.knpcode.springbootproject.model.Employee;
import com.knpcode.springbootproject.service.EmployeeService;

@RestController
@RequestMapping("/employee")
public class EmployeeController {
  @Autowired
  EmployeeService empService;

  @GetMapping("/{id}")
  public Employee getEmployeeById(@PathVariable int id) {
    return empService.getEmployeeById(id);
  }

  @GetMapping
  public List<Employee> getAllEmployees(){
    return empService.getAllEmployees();
  }

  @DeleteMapping("/{id}")
  @ResponseStatus(HttpStatus.OK)
  public void deleteEmployeeById(@PathVariable int id){
    empService.deleteEmployeeById(id);
  }
  @PostMapping
  @ResponseStatus(HttpStatus.CREATED)
  public Employee addEmployee(@RequestBody Employee emp) {
    return empService.addEmployee(emp);
  }
  @GetMapping("/lastname/{lastName}")
  public List<Employee> getEmployeeByLastName(@PathVariable String lastName) {
    return empService.getEmployeeByLastName(lastName);
  }
}

DB Configuration

We have already seen how Spring Data takes the responsibility of deriving queries for the query methods so you don’t have to write boiler plate code for CRUD functionality. Now see the magic of Spring Boot and the reduction in configuration that is required.

By default Spring boot reads properties file at this location src/main/resources/application.properties

You must define the DB connection attributes and Hibernate related properties in the application.properties file.

spring.datasource.url=jdbc:mysql://localhost:3306/knpcode
spring.datasource.username=
spring.datasource.password=

spring.jpa.properties.hibernate.sqldialect=org.hibernate.dialect.MySQLInnoDBDialect
spring.jpa.properties.hibernate.showsql=true

Notice the keys used in the key/value pair stored in properties file, ensure that the same keys are used.

With this properties file and the jars in classpath for Hibernate and MySQL, Spring Boot can automatically configure Hibernate as JPA Vendor and set the DataSource using the DB connection attributes defined in application.properties file.

Create Spring Boot Application Class

Here is an application class with the main method which is the entry point for Spring Boot application.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JPAApp {
  public static void main(String[] args) {
    SpringApplication.run(JPAApp.class, args);
  }
}

@SpringBootApplication is a convenience annotation that adds all of the following annotations-

  1. @Configuration annotation tags the class as a source of bean definitions for the application context.
  2. @EnableAutoConfiguration tells Spring Boot to enable auto configuration so that beans are created automatically based on classpath settings, other beans, and various property settings. For example starter spring-boot-starter-web adds Tomcat and Spring MVC so the auto-configuration assumes that you are developing a web application and sets up Spring accordingly which includes setting up a DispatcherServlet.
  3. @ComponentScan tells Spring to look recursively for other components, configurations and services inside this package and register them.

The main method is the application entry point which delegates to Spring Boot’s SpringApplication class by calling run. SpringApplication bootstraps this Spring Data JPA application, starting Spring, which, in turn, starts the embedded Tomcat web server.

Running the application

1- You can run it as a stand alone Java application by running the class with the main method (JPAApp.java) from Eclipse IDE itself.

Right click JPAApp.java – Run As – Java Application

If everything works fine you should see a message on console similar to following (part from messages for Initializing WebApplicationContext, Hibernate configuration)

Tomcat started on port(s): 8080 (http) with context path ''
com.knpcode.springbootproject.JPAApp     : Started JPAApp

2- Dependency spring-boot-starter-parent also provides a run goal that you can use to start the application. Type mvn spring-boot:run from the root project directory to start the application.

F:\knpcode\Spring WorkSpace\SpringBootProject>mvn spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building SpringBootProject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.1.6.RELEASE:run (default-cli) > test-compile @ SpringBootProject >>>

2019-09-23 19:08:36.733  INFO 8476 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-09-23 19:08:36.748  INFO 8476 --- [           main] com.knpcode.springbootproject.JPAApp     : Started JPAApp in 4.958 seconds (JVM running for 22.892)

3- You can also create a completely self-contained executable jar file using run mvn package from the command line.

F:\knpcode\Spring WorkSpace\SpringBootProject>mvn package

[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ SpringBootProject ---
[INFO] Building jar: F:\knpcode\Spring WorkSpace\SpringBootProject\target\SpringBootProject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.6.RELEASE:repackage (repackage) @ SpringBootProject ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

To run application using the created jar, use the java -jar command, as follows-

java -jar target\SpringBootProject-0.0.1-SNAPSHOT.jar

Once the application is deployed on Tomcat Server, using any of the options given above, you can test the webservice using Postman client.

Adding employee

Spring Boot Spring Data JPA

Note that the request selected is POST and the URL is http://localhost:8080/SpringJPAProject/employee

Data is sent as request body in JSON format. In the response added Employee data is sent back.

Get all employees

Spring RESTful

Get Employee by last name

You can also also send requests directly from browser as done for this request.

spring data

Delete Employee by ID

Delete Employee

That's all for the topic Spring Boot + Spring Data JPA + MySQL + Spring RESTful. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment