Spring Boot REST + JPA + Hibernate + MySQL Example
March 17, 2017
This page will walk through spring boot REST + JPA + hibernate + MySQL example. Here we will create a REST application that will perform CRUD operation using MySQL. Spring boot provides default database configurations when it scans Spring Data JPA in classpath. Spring boot uses spring-boot-starter-data-jpa starter to configure spring JPA with hibernate. For data source we need to configure data source properties starting with
spring.datasource.*
in application.properties and spring boot JPA will configure data source automatically. Spring boot prefers tomcat pooling on first place then HikariCP and then Commons DBCP on the basis of availability. We need not to write spring configuration classes and just by configuring properties in application.properties we are done. In our DAO class we can get instance of EntityManager
using dependency injection. To run the application we will create a class with main()
method that will call SpringApplication.run()
to start the application with embedded tomcat. The class with main()
method will be annotated with @SpringBootApplication
. In our application, at client side we will use RestTemplate
to consume REST web service. Now find the complete example step by step.
Contents
- Software Used
- MySQL Database Schema
- Project Structure in Eclipse
- Maven File
- Configure Properties in application.properties File
- Create DAO for CRUD Operation
- Create Service
- Create Controller
- Create Main Class using SpringApplication
- Create Client using RestTemplate
- Test Application
- Reference
- Download Source Code
Software Used
We are using following software in our example.1. Java 8
2. Spring Boot 1.5.2.RELEASE
3. Maven 3.3
4. MySQL 5.5
5. Eclipse Mars
MySQL Database Schema
Find the database schema with seed data.Database Schema
-- Dumping database structure for concretepage CREATE DATABASE IF NOT EXISTS `concretepage`; USE `concretepage`; -- Dumping structure for table concretepage.articles CREATE TABLE IF NOT EXISTS `articles` ( `article_id` int(5) NOT NULL AUTO_INCREMENT, `title` varchar(200) NOT NULL, `category` varchar(100) NOT NULL, PRIMARY KEY (`article_id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1; -- Dumping data for table concretepage.articles: ~3 rows (approximately) INSERT INTO `articles` (`article_id`, `title`, `category`) VALUES (1, 'Java Concurrency', 'Java'), (2, 'Hibernate HQL ', 'Hibernate'), (3, 'Spring MVC with Hibernate', 'Spring');
Article.java
package com.concretepage.entity; import java.io.Serializable; 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="articles") public class Article implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="article_id") private int articleId; @Column(name="title") private String title; @Column(name="category") private String category; public int getArticleId() { return articleId; } public void setArticleId(int articleId) { this.articleId = articleId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
Project Structure in Eclipse
Find the project structure in eclipse.
Maven File
Find the maven file used in our example.pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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.concretepage</groupId> <artifactId>spring-boot-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-demo</name> <description>Spring Boot Demo Project</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring-boot-starter-parent : Parent POM for dependency management.
spring-boot-starter-web: Starter for building web, REST applications. It uses tomcat server as default embedded server.
spring-boot-starter-data-jpa: Starter for spring data JPA with hibernate.
spring-boot-devtools : It provides developer tools. These tools are helpful in application development mode. One of the features of developer tool is automatic restart of the server for any change in code.
spring-boot-maven-plugin : It is used to create executable JAR of the application.
Configure Properties in application.properties File
The properties related to database, hibernate and logging need to be configured inapplication.properties
file. These properties will automatically be read by Spring boot.
application.properties
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/concretepage spring.datasource.username=root spring.datasource.password= spring.datasource.tomcat.max-wait=20000 spring.datasource.tomcat.max-active=50 spring.datasource.tomcat.max-idle=20 spring.datasource.tomcat.min-idle=15 spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect spring.jpa.properties.hibernate.id.new_generator_mappings = false spring.jpa.properties.hibernate.format_sql = true logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.datasource.*
will automatically be read by Spring boot JPA. To change the Hibernate properties we will use prefix spring.jpa.properties.*
with Hibernate property name. On the basis of given data source URL, Spring boot can automatically identify data source driver class. So we need not to configure diver class.
Find the properties to configure
JpaBaseConfiguration
and HibernateJpaAutoConfiguration
in application.properties
.
spring.data.jpa.repositories.enabled: It enables JPA repositories. The default value is true.
spring.jpa.database: It targets database to operate on. By default embedded database is auto-detected.
spring.jpa.database-platform: It is used to provide the name of database to operate on. By default it is auto- detected.
spring.jpa.generate-ddl: It is used to initialize schema on startup. By default the value is false.
spring.jpa.hibernate.ddl-auto: It is DDL mode used for embedded database. Default value is create-drop.
spring.jpa.hibernate.naming.implicit-strategy: It is Hibernate 5 implicit naming strategy fully qualified name.
spring.jpa.hibernate.naming.physical-strategy: It is Hibernate 5 physical naming strategy fully qualified name.
spring.jpa.hibernate.use-new-id-generator-mappings: It is used for Hibernate
IdentifierGenerator
for AUTO, TABLE and SEQUENCE.
spring.jpa.open-in-view: The default value is true. It binds a JPA
EntityManager
to the thread for the entire processing of the request.
spring.jpa.properties.*: It sets additional native properties to set on the JPA provider.
spring.jpa.show-sql: It enables logging of SQL statements. Default value is false.
Create DAO for CRUD Operation
Find the DAO used in example to perform CRUD operation. To inject the instance ofEntityManager
we will use @PersistenceContext
.
IArticleDAO.java
package com.concretepage.dao; import java.util.List; import com.concretepage.entity.Article; public interface IArticleDAO { List<Article> getAllArticles(); Article getArticleById(int articleId); void addArticle(Article article); void updateArticle(Article article); void deleteArticle(int articleId); boolean articleExists(String title, String category); }
package com.concretepage.dao; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.concretepage.entity.Article; @Transactional @Repository public class ArticleDAO implements IArticleDAO { @PersistenceContext private EntityManager entityManager; @Override public Article getArticleById(int articleId) { return entityManager.find(Article.class, articleId); } @SuppressWarnings("unchecked") @Override public List<Article> getAllArticles() { String hql = "FROM Article as atcl ORDER BY atcl.articleId"; return (List<Article>) entityManager.createQuery(hql).getResultList(); } @Override public void addArticle(Article article) { entityManager.persist(article); } @Override public void updateArticle(Article article) { Article artcl = getArticleById(article.getArticleId()); artcl.setTitle(article.getTitle()); artcl.setCategory(article.getCategory()); entityManager.flush(); } @Override public void deleteArticle(int articleId) { entityManager.remove(getArticleById(articleId)); } @Override public boolean articleExists(String title, String category) { String hql = "FROM Article as atcl WHERE atcl.title = ? and atcl.category = ?"; int count = entityManager.createQuery(hql).setParameter(1, title) .setParameter(2, category).getResultList().size(); return count > 0 ? true : false; } }
Create Service
Find the service class used in our example.IArticleService.java
package com.concretepage.service; import java.util.List; import com.concretepage.entity.Article; public interface IArticleService { List<Article> getAllArticles(); Article getArticleById(int articleId); boolean addArticle(Article article); void updateArticle(Article article); void deleteArticle(int articleId); }
package com.concretepage.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.concretepage.dao.IArticleDAO; import com.concretepage.entity.Article; @Service public class ArticleService implements IArticleService { @Autowired private IArticleDAO articleDAO; @Override public Article getArticleById(int articleId) { Article obj = articleDAO.getArticleById(articleId); return obj; } @Override public List<Article> getAllArticles(){ return articleDAO.getAllArticles(); } @Override public synchronized boolean addArticle(Article article){ if (articleDAO.articleExists(article.getTitle(), article.getCategory())) { return false; } else { articleDAO.addArticle(article); return true; } } @Override public void updateArticle(Article article) { articleDAO.updateArticle(article); } @Override public void deleteArticle(int articleId) { articleDAO.deleteArticle(articleId); } }
Create Controller
Find the controller class that will expose web service methods.ArticleController.java
package com.concretepage.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; 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.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.util.UriComponentsBuilder; import com.concretepage.entity.Article; import com.concretepage.service.IArticleService; @Controller @RequestMapping("user") public class ArticleController { @Autowired private IArticleService articleService; @GetMapping("article/{id}") public ResponseEntity<Article> getArticleById(@PathVariable("id") Integer id) { Article article = articleService.getArticleById(id); return new ResponseEntity<Article>(article, HttpStatus.OK); } @GetMapping("articles") public ResponseEntity<List<Article>> getAllArticles() { List<Article> list = articleService.getAllArticles(); return new ResponseEntity<List<Article>>(list, HttpStatus.OK); } @PostMapping("article") public ResponseEntity<Void> addArticle(@RequestBody Article article, UriComponentsBuilder builder) { boolean flag = articleService.addArticle(article); if (flag == false) { return new ResponseEntity<Void>(HttpStatus.CONFLICT); } HttpHeaders headers = new HttpHeaders(); headers.setLocation(builder.path("/article/{id}").buildAndExpand(article.getArticleId()).toUri()); return new ResponseEntity<Void>(headers, HttpStatus.CREATED); } @PutMapping("article") public ResponseEntity<Article> updateArticle(@RequestBody Article article) { articleService.updateArticle(article); return new ResponseEntity<Article>(article, HttpStatus.OK); } @DeleteMapping("article/{id}") public ResponseEntity<Void> deleteArticle(@PathVariable("id") Integer id) { articleService.deleteArticle(id); return new ResponseEntity<Void>(HttpStatus.NO_CONTENT); } }
1. Create :
HTTP Method: POST, URL: /user/article
2. Read :
HTTP Method: GET, URL: /user/article/{id}
HTTP Method: GET, URL: /user/articles
3. Update :
HTTP Method: PUT, URL: /user/article
4. Delete :
HTTP Method: DELETE, URL: /user/article/{id}
Create Main Class using SpringApplication
Create a class withmain()
method that will call SpringApplication.run()
to run the application. First all JAR dependencies are downloaded and then the project is compiled and then embedded tomcat server is started.
MyApplication.java
package com.concretepage; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
@SpringBootApplication
annotation that is equivalent to @Configuration
, @EnableAutoConfiguration
and @ComponentScan
annotations.
Create Client using RestTemplate
Find the client that will consume REST web services. We are usingRestTemplate
to communicate with REST web service server.
RestClientUtil.java
package com.concretepage.client; import java.net.URI; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import com.concretepage.entity.Article; public class RestClientUtil { public void getArticleByIdDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article.class, 1); Article article = responseEntity.getBody(); System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle() +", Category:"+article.getCategory()); } public void getAllArticlesDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/articles"; HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class); Article[] articles = responseEntity.getBody(); for(Article article : articles) { System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle() +", Category: "+article.getCategory()); } } public void addArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setTitle("Spring REST Security using Hibernate"); objArticle.setCategory("Spring"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); URI uri = restTemplate.postForLocation(url, requestEntity); System.out.println(uri.getPath()); } public void updateArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article"; Article objArticle = new Article(); objArticle.setArticleId(1); objArticle.setTitle("Update:Java Concurrency"); objArticle.setCategory("Java"); HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers); restTemplate.put(url, requestEntity); } public void deleteArticleDemo() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/user/article/{id}"; HttpEntity<Article> requestEntity = new HttpEntity<Article>(headers); restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Void.class, 4); } public static void main(String args[]) { RestClientUtil util = new RestClientUtil(); //util.getArticleByIdDemo(); util.getAllArticlesDemo(); //util.addArticleDemo(); //util.updateArticleDemo(); //util.deleteArticleDemo(); } }
Test Application
To test the application, first create table in MySQL as given in the example. Then we can run REST web service in following ways.1. Using Eclipse: Download the project source code using the download link given at the end of page. Import the project into eclipse. Using command prompt, go to the root folder of the project and run.
mvn clean eclipse:eclipse
MyApplication
by clicking Run as -> Java Application. Tomcat server will be started.
2. Using Maven Command: Download the project source code. Go to the root folder of the project using command prompt and run the command.
mvn spring-boot:run
3. Using Executable JAR: Using command prompt, go to the root folder of the project and run the command.
mvn clean package
java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar
Now we are ready to test the application. To run client, go to the
RestClientUtil
class in eclipse and click on Run as -> Java Application.
We can also test application using Postman. Find the print screen.
