In this tutorial, we’ll discuss how to integrate Spring Boot and Hibernate. In this tutorial, we’ll create a REST application and will integrate Hibernate.
Step 1: Create a Spring Boot application with Hibernate dependencies
In this tutorial we are using MySql as database. We’ll create a Spring Boot application with following dependencies:
- spring-boot-starter-data-jpa
- spring-boot-starter-web
- mysql-connector-java
You can use Spring Initializr to create your application. Using Spring Initializr is very simple and easy to use. Once you have created your application using Spring Initializr, you can import your application in your IDE. We are using STS for this tutorial.
In maven project the pom.xml
looks like this.
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.learnitweb</groupId> <artifactId>springHibernateDemo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springHibernateDemo</name> <description>Demo of Spring Boot with Hibernate</description> <properties> <java.version>1.8</java.version> </properties> <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> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
If spring-boot-starter-data-jpa
dependency is used, Spring will try to configure the datasource. Java’s javax.sql.DataSource
interface provides a standard method of working with database connections. Typically, a datasource uses a URL along with credentials to establish a database connection. After creating the application, if you try to start the application, you may get the following error:
*************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
At least the
spring.datasource.url
property should be set otherwise, Spring Boot tries to auto-configure an embedded database.
Step 2. Configuration
Next step is to defined the properties in application.properties
to configure the database connection details. We are using the following properties in application.properties
.
spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=admin spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect # 'create' will generate DDL spring.jpa.hibernate.ddl-auto=create # property to show sql in console spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
Step 3: Create Entity
We are creating a Customer
entity. We are using @Table
annotation to specify the table name with which this entity will be mapped in database. This annotation is not mandatory. If not used table name will be same as that of entity.
Customer.java
package com.learnitweb.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "Customer") public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String firstName; private String lastName; public Customer() { } public Long getId() { return id; } public void setId(Long 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; } }
Step 4: Write controller, service and repository
CustomerController.java
package com.learnitweb.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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.RestController; import com.learnitweb.dto.CustomerData; import com.learnitweb.service.CustomerService; @RestController @RequestMapping("/customers") public class CustomerController { @Autowired CustomerService customerService; /* * Controller to get all customers */ @GetMapping public List<CustomerData> getCustomers() { return customerService.getAllCustomers(); } /* * Controller to get detail of particular customer */ @GetMapping("/customer/{id}") public CustomerData getCustomer(@PathVariable Long id) { return customerService.getCustomerById(id); } /* * Controller to save customer */ @PostMapping("/customer") public CustomerData saveCustomer(final @RequestBody CustomerData customerData) { return customerService.saveCustomer(customerData); } }
CustomerRepository.java
package com.learnitweb.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.learnitweb.entity.Customer; @Repository public interface CustomerRepository extends JpaRepository<Customer, Long> { }
CustomerService.java
package com.learnitweb.service; import java.util.List; import com.learnitweb.dto.CustomerData; public interface CustomerService { public CustomerData saveCustomer(CustomerData customer); public List<CustomerData> getAllCustomers(); public CustomerData getCustomerById(Long customerId); }
CustomerServiceImpl.java
package com.learnitweb.service.impl; import java.util.ArrayList; import java.util.List; import java.util.Optional; import javax.persistence.EntityNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.learnitweb.dto.CustomerData; import com.learnitweb.entity.Customer; import com.learnitweb.repository.CustomerRepository; import com.learnitweb.service.CustomerService; @Service public class CustomerServiceImpl implements CustomerService { @Autowired CustomerRepository customerRepository; @Override public CustomerData saveCustomer(CustomerData customer) { Customer customerEntity = populateCustomerEntity(customer); return populateCustomerData(customerRepository.save(customerEntity)); } @Override public List<CustomerData> getAllCustomers() { List<CustomerData> customers = new ArrayList<>(); List<Customer> customerList = customerRepository.findAll(); customerList.forEach(customer -> { customers.add(populateCustomerData(customer)); }); return customers; } @Override public CustomerData getCustomerById(Long customerId) { Optional<Customer> customerEntity = customerRepository.findById(customerId); if (customerEntity.isPresent()) { return populateCustomerData(customerEntity.get()); } else { throw new EntityNotFoundException("Customer not found"); } } private CustomerData populateCustomerData(final Customer customer) { CustomerData customerData = new CustomerData(); customerData.setId(customer.getId()); customerData.setFirstName(customer.getFirstName()); customerData.setLastName(customer.getLastName()); return customerData; } private Customer populateCustomerEntity(CustomerData customerData) { Customer customer = new Customer(); customer.setFirstName(customerData.getFirstName()); customer.setLastName(customerData.getLastName()); return customer; } }
CustomerData.java
package com.learnitweb.dto; public class CustomerData { private Long id; private String firstName; private String lastName; public Long getId() { return id; } public void setId(Long 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; } }
Step 5: Test your application
5.1 Saving customer (POST)
5.2 Get customer by Id
5.3 Get all customers
Reading database username and password from environment in Spring Boot
You may not want to hard code database username and password in application.properties
. One reason to not do so is that if you save database username and password in property file then these will be committed as a part of your code in your version control system.
One solution is to use database username and password as environment property. In our case, we have created two environment variables DB_USER
and DB_PASSWORD
to save database username and password. You then have to change application.properties
file like the following to read database username and password from environment:
spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASSWORD}
Note: If you are trying this in your local, you need to restart your IDE after creating environment variables.