Object Computing, Inc. (OCI) released Micronaut 1.3 featuring the milestone release of project Micronaut Data 1.0, "a database access toolkit that uses Ahead of Time (AoT) compilation to pre-compute queries for repository interfaces that are then executed by a thin, lightweight runtime layer." Additional features in Micronaut 1.3 include immutable configuration properties; cache support for Ehache, Hazelcast, Infinispan, and more; initial support for Kotlin co-routines and Asynchronous Flow; support for GraalVM 19.3 and XML serialization/deserialization with Jackson XML; and improvements to performance and memory consumption.
Originally known as Micronaut Predator, Micronaut Data provides a general API for translating a Query
model into a query at compile time and provides runtime support for JPA/Hibernate and SQL/JDBC backends. The Micronaut Data team plans to support other database Implementations in the future. Micronaut Data supports H2, MySQL 5.5+, Oracle 12c+, PostgreSQL 9.5+, and SQLServer 2012+.
Inspired by GORM and Spring Data, Micronaut Data improves on these two technologies by eliminating the runtime model that uses reflection, eliminating query translation that uses regular expressions and pattern matching, and adding type safety. The use of reflection in GORM and Spring Data for modeling relationships between entities leads to more memory consumption.
Getting Started
Like any other Micronaut application, a skeletal, yet working Micronaut Data application can be created via the command line using the appropriate parameters for either a JPA/Hibernate or SQL/JDBC backend as a starting point for a more comprehensive application:
$ mn create-app myapp --features data-hibernate-jpa
$ mn create-app myapp --features data-jdbc
With Gradle set as the default build tool for Micronaut applications, the generated build.gradle
file will contain the appropriate dependencies:
implementation "io.micronaut.data:micronaut-data-hibernate-jpa"
implementation "io.micronaut.data:micronaut-data-jdbc"
Consider a simple movie H2 database application modeled with Micronaut Data. Two tables, movie
and director
, will have corresponding POJOs, repositories and controllers in the application. The Movie
class, representing a movie
table, will capture some movie information and define a universally unique identifier (UUID
) and a @ManyToOne
relationship with a director
table.
@Entity
public class Movie {
@Id
@AutoPopulated
private UUID id;
private String name;
private MovieType type;
private int year;
@ManyToOne
private Director director;
@Creator
public Movie(String name, @Nullable Director director, MovieType type, int year) {
// setter methods
}
}
@AutoPopulated
identifies annotations that are auto-populated by Micronaut Data and @Creator
is an annotation applicable to a primary constructor.
Creating a Repository
Consider the following repository interface:
@JdbcRepository(dialect = Dialect.H2)
public interface MovieRepository extends CrudRepository<Movie,Long> {
Movie findByName(String name);
@Join("director")
Optional<Movie> findByName(String lastName);
}
The MovieRepository
interface is defined as a data repository via the @JdbcRepository
annotation, a stereotype repository that configures a Repository
to use raw SQL encoding. An implementation is automatically generated by Micronaut Data at runtime. The CrudRepository
interface automatically provides create, read, update and delete operations. The movie
table is joined to the director
table via the @Join
annotation.
Query Computation
Based on an application's POJOs, repositories and controllers, Micronaut Data computes the appropriate queries. Consider the following test:
@Inject
BeanContext beanContext;
@Test
void testQuery() {
String query = beanContext.getBeanDefinition(MovieRepository.class)
.getRequiredMethod("findByName",String.class)
.getAnnotationMetadata()
.stringValue(Query.class)
.get();
assertEquals(
"SELECT ... FROM ... INNER JOIN ... ON ... WHERE ...",
query
);
}
The injected Micronaut BeanContext
will generate a full query based on the findByName()
method defined in the MovieRepository
interface.
SELECT movie_.`id`,movie_.`name`,movie_.`director_id`,movie_.`type`,movie_.`year`,movie_director_.`last_name` AS
director_last_name,movie_director_.`first_name` AS director_first_name,movie_director_.`name` AS director_name FROM
`movie` movie_ INNER JOIN `director` movie_director_ ON movie_.`director_id`=movie_director_.`id` WHERE (movie_.`name` = ?)
The full comprehensive example can be found on GitHub.
The Road to Micronaut 2.0
Looking ahead to Micronaut 2.0, the Micronaut team is planning improvements such as:
- Reactive Micronaut Data for SQL, Neo4j and MongoDB
- HTTP/2 support
- Improvements to serverless support
- New build plugins for Maven and Gradle
- Further performance refinements
Micronaut Data joins other Micronaut projects such as Micronaut AWS, Micronaut GCP, Micronaut for Spring, Micronaut RabbitMQ, and Micronaut Test.
Editor's Note
A recent minor Micronaut 1.3.3 release now supports GraalVM 20.0.0.