Build REST CRUD APIs with Micronaut and Hibernate

Hello everyone, today we will learn how to build RESTful CRUD APIs using Micronaut and Hibernate with the help of one simple example.

Related topic,

Micronaut is a modern, JVM-predicated, full-stack Java framework designed for building modular, facilely testable JVM applications with support for Java, Kotlin and the Groovy language.

Micronaut  provides:

  • Dependency Injection and Inversion of Control (IoC)
  • Aspect-Oriented Programming (AOP)
  • Sensible Defaults and Auto-ConfigurationMessage-Driven Applications
  • HTTP Routing
  • Client-Side Load Balancing
  • Command-Line Applications
  • HTTP ServersDistributed Configuration
  • Service Discovery
  • Fast startup time
  • Reduced memory footprint
  • Minimal use of reflection
  • Minimal use of proxies
  • No runtime bytecode generation
  • Easy Unit Testing

Technologies used:

  • Java 11
  • Micronaut 3.1.1
  • Micronaut-Hibernate-JPA 3.1.1
  • H2DB
  • Micronaut-Hikari-Cp 3.1.1
  • Maven 3.6.3

Final Project Structure:



Dependency management - Maven - Pom.xml

A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project. It contains default values for most projects. Some of the configurations that can be designated in the POM is the project dependencies, the plugins or goals that can be executed, the build profiles, and so on. Other information such as the project version, description, developers, mailing lists, and such can withal be designated.
<?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>org.knf.dev.demo</groupId>
<artifactId>micronaut-hibernate-crud</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>

<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.1</version>
</parent>

<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>3.1.1</micronaut.version>
<exec.mainClass>org.knf.dev.demo.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>

<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-hibernate-jpa</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-jdbc-hikari</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths
combine.children="append">
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-validation</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=org.knf.dev.demo</arg>
<arg>-Amicronaut.processing.module=micronaut-hibernate-crud</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>


Data source & JPA configuration in src/main/resources/application.yml

micronaut:
application:
name: micronautHibernateCrud
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
driverClassName: org.h2.Driver
username: sa
password: ''
jpa.default.properties.hibernate.hbm2ddl.auto: update

jpa:
default:
properties:
hibernate:
hbm2ddl:
auto: update
show_sql: true


Entity class

package org.knf.dev.demo.entity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String emailId;

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;
}

public String getEmailId() {
return emailId;
}

public void setEmailId(String emailId) {
this.emailId = emailId;
}
public User(Long id, String firstName, String lastName, String emailId) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}

public User() {
super();
}
}


UserRepository

package org.knf.dev.demo.repository;

import java.util.List;
import java.util.Optional;
import org.knf.dev.demo.entity.User;

public interface UserRepository {
Optional<User> findById(Long id);

User save(User user);

void deleteById(Long id);

List<User> findAll();

void update(Long id, User user);
}


UserRepositoryImpl

package org.knf.dev.demo.repository.impl;

import java.util.List;
import java.util.Optional;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import org.knf.dev.demo.entity.User;
import org.knf.dev.demo.repository.UserRepository;
import io.micronaut.transaction.annotation.ReadOnly;
import io.micronaut.transaction.annotation.TransactionalAdvice;
import jakarta.inject.Singleton;

@Singleton
public class UserRepositoryImpl implements UserRepository {
private final EntityManager entityManager;

public UserRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;

}

@Override
@ReadOnly
public Optional<User> findById(Long id) {
return Optional.ofNullable(entityManager.find(User.class, id));
}

@Override
@TransactionalAdvice
@Transactional
public User save(User user) {
entityManager.persist(user);
return user;

}

@Override
@TransactionalAdvice
@Transactional
public void deleteById(Long id) {
findById(id).ifPresent(entityManager::remove);
}

@ReadOnly
public List<User> findAll() {
return entityManager.
createQuery("SELECT c FROM User c").
getResultList();
}

@Override
@Transactional
@TransactionalAdvice
public void update(Long id, User user) {
User userToUpdate = entityManager.find(User.class, id);
if (null != userToUpdate) {
userToUpdate.setFirstName(user.getFirstName());
userToUpdate.setLastName(user.getLastName());
userToUpdate.setEmailId(user.getEmailId());
} else {
throw new RuntimeException("No such user available");
}
}
}



UserController

package org.knf.dev.demo.controller;

import java.util.List;
import java.util.Optional;
import org.knf.dev.demo.entity.User;
import org.knf.dev.demo.repository.UserRepository;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Put;
import io.micronaut.scheduling.TaskExecutors;
import io.micronaut.scheduling.annotation.ExecuteOn;

@ExecuteOn(TaskExecutors.IO)
@Controller("/users")
public class UserController {

protected final UserRepository userRepository;

public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Get
public List<User> getUsers() {
return userRepository.findAll();
}

@Get("/{id}")
public Optional<User> getUser(Long id) {
return userRepository.findById(id);
}

@Put("/{id}")
public void updateUser(Long id, @Body User user) {
userRepository.update(id, user);
}

@Post
public User addUser(@Body User user) {
return userRepository.save(user);
}

@Delete("/{id}")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}


Main Class

package org.knf.dev.demo;

import io.micronaut.runtime.Micronaut;

public class Application {

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


Verify REST APIs

Run as Java Application 

or
mvn mn:run
 

Add User:



Get All User:



Get User By Id:



Delete User:



Update User:


Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete