Bright Java Tutorial

is brought to you by DoITBright LLC

Spring Boot

Hibernate and REST Example

This lesson will show us a very simple example on how to create our first REST web service that implements object relational mapping using Spring Boot and Hibernate framework. It is assumed that you have your JDK and Eclipse IDE setup on your local machine. Create a Maven Webapp Project and name it as 'SpringBootRestHibernate'. Then edit your 'pom.xml' so that it will look like this...

  <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/maven-v4_0_0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.brightjavatutorial.spring.boot</groupId>
    <artifactId>SpringBootRestHibernate</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBootRestHibernate Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <parent>
      <groupId>
        org.springframework.boot
      </groupId>
      <artifactId>
        spring-boot-starter-parent
      </artifactId>
      <version>
        1.3.5.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-starter-tomcat
        </artifactId>
        <scope>
          provided
        </scope>
      </dependency>

      <dependency>
        <groupId>
          org.apache.tomcat.embed
        </groupId>
        <artifactId>
          tomcat-embed-jasper
        </artifactId>
        <scope>
          provided
        </scope>
      </dependency>
    </dependencies>

    <build>
      <plugins>
        <plugin>
          <groupId>
            org.springframework.boot
          </groupId>
          <artifactId>
            spring-boot-maven-plugin
          </artifactId>
        </plugin>
      </plugins>
    </build>
  </project>
                           


Create a Java file under the package 'example'. Make sure that this package will be in 'C:\SpringBootStuff\SpringBootRestHibernate\src\main\java\' directory. Name it as 'Account.java'.

  package example;

  import java.util.Date;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.Table;
  import org.springframework.format.annotation
    .DateTimeFormat;

  @Entity
  @Table(name = "ACCOUNT")
  public class Account {

    public Account() {
		
    }
	
    public Account(Integer accountId) {
      this.accountId = accountId;
    }
	
    public Account(String email, Date createDate) {
      this.email = email;
      this.createDate = createDate;
    }
	
    @Id
    @Column(name = "ACCOUNT_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer accountId;
	
    @Column(name = "EMAIL")
    private String email;
	
    @DateTimeFormat(pattern="yyyy-MM-dd")  
    @Column(name = "CREATE_DATE")
    private Date createDate;

    public Integer getAccountId() {
      return accountId;
    }

    public void setAccountId(Integer accountId) {
      this.accountId = accountId;
    }

    public String getEmail() {
      return email;
    }

    public void setEmail(String email) {
      this.email = email;
    }

    public Date getCreateDate() {
      return createDate;
    }

    public void setCreateDate(Date createDate) {
      this.createDate = createDate;
    }
	
  }
                            


This class is marked with an '@Entity' annotation. This will serve as a the POJO that maps to the deatabase. Look at the class, it also have the '@Table' annotation which also specifies the name of the table where it maps to.

Since we wish to map the above class to a table named 'ACCOUNT', this means we have to actually create the database and the table in our MySQL database.

  CREATE DATABASE EXAMPLEDB;
                            


  CREATE TABLE ACCOUNT (ACCOUNT_ID INT PRIMARY KEY 
      AUTO_INCREMENT NOT NULL, EMAIL VARCHAR(65) NOT NULL, 
      CREATE_DATE DATE);
                            


Let us now create a class which will be responsible for the configuration of the connection to the database.

  package example;

  import java.util.Properties;
  import javax.sql.DataSource;
  import 
    org.springframework.beans.factory.annotation.Autowired;
  import 
    org.springframework.context.annotation.Bean;
  import 
    org.springframework.context.annotation.Configuration;
  import org.springframework.core.env.Environment;
  import 
    org.springframework.dao.annotation
    .PersistenceExceptionTranslationPostProcessor;
  import 
    org.springframework.jdbc.datasource
    .DriverManagerDataSource;
  import 
    org.springframework.orm.jpa.JpaTransactionManager;
  import 
    org.springframework.orm.jpa
    .LocalContainerEntityManagerFactoryBean;
  import 
    org.springframework.orm.jpa.vendor
    .HibernateJpaVendorAdapter;
  import 
    org.springframework.transaction.annotation
    .EnableTransactionManagement;

  /**
   * Contains database configurations.
   */
  @Configuration
  @EnableTransactionManagement
  public class DatabaseConfig {

    @Bean
    public DataSource dataSource() {
      DriverManagerDataSource dataSource 
        = new DriverManagerDataSource();
      dataSource
        .setDriverClassName(env.getProperty("db.driver"));
      dataSource.setUrl(env.getProperty("db.url"));
      dataSource
        .setUsername(env.getProperty("db.username"));
      dataSource
        .setPassword(env.getProperty("db.password"));
      return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean 
      entityManagerFactory() {
      
      LocalContainerEntityManagerFactoryBean 
        entityManagerFactory =
        new LocalContainerEntityManagerFactoryBean();
    
      entityManagerFactory.setDataSource(dataSource);
    
      entityManagerFactory.setPackagesToScan(
        env.getProperty("entitymanager.packagesToScan"));
    
      HibernateJpaVendorAdapter vendorAdapter 
        = new HibernateJpaVendorAdapter();
      entityManagerFactory
        .setJpaVendorAdapter(vendorAdapter);
    
      Properties additionalProperties = new Properties();
      additionalProperties.put(
        "hibernate.dialect", 
        env.getProperty("hibernate.dialect"));
      additionalProperties.put(
        "hibernate.show_sql", 
        env.getProperty("hibernate.show_sql"));
      additionalProperties.put(
        "hibernate.hbm2ddl.auto", 
        env.getProperty("hibernate.hbm2ddl.auto"));
      entityManagerFactory
        .setJpaProperties(additionalProperties);
    
      return entityManagerFactory;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
      JpaTransactionManager transactionManager = 
        new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(
        entityManagerFactory.getObject());
      return transactionManager;
    }
  
    @Bean
    public PersistenceExceptionTranslationPostProcessor 
        exceptionTranslation() {
      return 
        new PersistenceExceptionTranslationPostProcessor();
    }
  
    @Autowired
    private Environment env;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private LocalContainerEntityManagerFactoryBean 
      entityManagerFactory;

  }
                            


Most likely, the above class that you wrote will remain the same most of the time. We do not do much changes in such kind of files. The matching configuration file for the above mentioned class will be the application.properties which is located in '/SpringBootRestHibernate/src/main/resources/' directory.

  # Database
  db.driver: com.mysql.jdbc.Driver
  db.url: jdbc:mysql://localhost:3306/EXAMPLEDB
  db.username: root
  db.password: root

  # Hibernate
  hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
  hibernate.show_sql: true
  hibernate.hbm2ddl.auto: update
  entitymanager.packagesToScan: example

  spring.mvc.view.prefix: /
  spring.mvc.view.suffix: .jsp
                            


The next thing to do is create the Data Access Object. This is where the interaction with the database actually happens.

  package example;

  import java.util.List;
  import javax.persistence.EntityManager;
  import javax.persistence.PersistenceContext;
  import javax.transaction.Transactional;
  import org.springframework.stereotype.Repository;

  @Repository
  public class AccountDao {
	
    @PersistenceContext
    private EntityManager entityManager;
	
    public void create(Account account) {
      entityManager.persist(account);
      return;
    }
  
    public void delete(Account account) {
      if (entityManager.contains(account)) {
        entityManager.remove(account);
      } else {
        entityManager.remove(entityManager.merge(account));
      }
      return;
    }
  
    @SuppressWarnings("unchecked")
    public List getAll() {
      return 
        entityManager.createQuery("from Account")
        .getResultList();
    }
  
    public Account getById(Integer accountId) {
      return entityManager.find(Account.class, accountId);
    }
  
    public void update(Account account) {
      entityManager.merge(account);
      return;
    }
  
    public Account getByEmail(String email) {
      return (Account) entityManager.createQuery(
        "from Account where email = :email")
        .setParameter("email", email)
        .getSingleResult();
    }
  }
                            


Then, we have to create a service class. This will handle the transaction from the AccountDao. Notice that this class is marked with '@Service' annotation and each method is marked with '@Transactional'.

  package example;

  import javax.transaction.Transactional;
  import 
    org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;

  @Service
  public class AccountService {
	
    @Autowired
    private AccountDao accountDao;

    @Transactional
    public Account create(Account account) {
      accountDao.create(account);
      return account;
    }
	
    @Transactional
    public Account getById(Integer accountId) {
      return accountDao.getById(accountId);
    }
  }
                            


It is now time to create our controller. The controller is where we will map the URL and receive the parameters.

  package example;

  import java.util.Date;
  import javax.validation.Valid;
  import 
    org.springframework.beans.factory.annotation.Autowired;
  import 
    org.springframework.web.bind.annotation.PathVariable;
  import 
    org.springframework.web.bind.annotation.RequestBody;
  import 
    org.springframework.web.bind.annotation.RequestMapping;
  import 
    org.springframework.web.bind.annotation.RequestMethod;
  import 
    org.springframework.web.bind.annotation.RestController;

  @RestController
  public class AccountRestController {
	
    @Autowired
    private AccountService accountService;
	
    @RequestMapping(value = "/account", 
      method = RequestMethod.PUT)
    public Account 
      createAccount(@RequestBody @Valid Account account) {
      account.setCreateDate(
        new Date(
        account.getCreateDate().getTime() 
        + (24*60*60*1000)));
      accountService.create(account);
      return account;
    }
	
    @RequestMapping(value = "/account/{accountId}", 
      method = RequestMethod.GET)
    public Account 
      getAccount(@PathVariable Integer accountId) {
      return accountService.getById(accountId);
    }
}
                            


  package example;

  import org.springframework.boot.SpringApplication;
  import 
    org.springframework.boot.autoconfigure
      .SpringBootApplication;
  import 
    org.springframework.boot.builder
      .SpringApplicationBuilder;
  import 
    org.springframework.boot.context.web
      .SpringBootServletInitializer;

  @SpringBootApplication
  public class Application 
    extends SpringBootServletInitializer {
    
    @Override
    protected SpringApplicationBuilder configure(
      SpringApplicationBuilder application) {
      return application.sources(Application.class);
    }

    public static void main(String[] args) 
      throws Exception {
      SpringApplication.run(Application.class, args);
    }
  }
                            


We now have a web application that will be able to insert a record into the 'ACCOUNT' table. It could also retrieve all records, perform an update on a record and delete a record. Package the application into a WAR file and deploy it in your '\tomcat\webapps\' directory. Here are some example URL invocation to demonstrate each operation.
  • PUT : http://localhost:8080/SpringBootRestHibernate/account
  • {"email":"test@emailz.com","createDate":"2017-01-05"}
  • GET : http://localhost:8080/SpringBootRestHibernate/account/1



Back