In the previous post, we successfully created a Micronaut project and configured it to connect with H2, PostgreSQL, and MySQL databases.
You can check that out – Setting Up a Micronaut App with H2 / PostgreSQL / MySQL
Now itβs time to define:
- Entities β Java classes that map to database tables.
- Repositories β Interfaces that handle database operations (CRUD).
Micronaut Data makes this process extremely simple and type-safe, with compile-time query generation.

π What are Entities?
Entities represent database tables. Each entity is a simple Java class annotated with @Entity
. Every field represents a column in the table.
Micronaut Data supports both JPA annotations and its own Data annotations.
In our school management example, letβs create an entity for Student
.
π Directory Structure
We will organize the code under:
1 2 3 4 5 6 7 8 |
com.kscodes.micronaut.school βββ controllers βββ entities βββ repositories βββ services |
Creating the Student Entity
Let’s create our first entity under the entities
package.
File: com/kscodes/micronaut/school/entities/Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package com.kscodes.micronaut.school.entities; import io.micronaut.data.annotation.*; import java.time.LocalDate; @MappedEntity("students") public class Student { @Id @GeneratedValue(GeneratedValue.Type.IDENTITY) private Long id; @Column(nullable = false) private String name; private LocalDate dateOfBirth; private String email; public Student() {} public Student(String name, LocalDate dateOfBirth, String email) { this.name = name; this.dateOfBirth = dateOfBirth; this.email = email; } public Long getId() { return id; } public String getName() { return name; } public LocalDate getDateOfBirth() { return dateOfBirth; } public String getEmail() { return email; } public void setName(String name) { this.name = name; } public void setDateOfBirth(LocalDate dateOfBirth) { this.dateOfBirth = dateOfBirth; } public void setEmail(String email) { this.email = email; } } |
π Explanation:
@MappedEntity("students")
β Maps tostudents
table.@Id
β Marks primary key.@GeneratedValue
β Auto-generates ID.@Column(nullable = false)
β Ensures name cannot be null.- Fields like
dateOfBirth
andemail
are optional.
π What are Repositories?
Repositories are interfaces where you declare database operations.
Micronaut generates the full implementation at compile time.
No need to write SQL or boilerplate code!
π§ Creating the Student Repository
Let’s create a repository interface under repositories
package.
File: com/kscodes/micronaut/school/repositories/StudentRepository.java
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.kscodes.micronaut.school.repositories; import com.kscodes.micronaut.school.entities.Student; import io.micronaut.data.annotation.Repository; import io.micronaut.data.repository.CrudRepository; @Repository public interface StudentRepository extends CrudRepository<Student, Long> { } |
π Explanation:
@Repository
β Marks this as a Micronaut Data repository.CrudRepository<Student, Long>
β Provides all basic CRUD methods:save()
findById()
findAll()
deleteById()
π₯ Finder Methods
Micronaut Data allows you to define custom queries by just writing method names!
Example: Find students by name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.kscodes.micronaut.school.repositories; import com.kscodes.micronaut.school.entities.Student; import io.micronaut.data.annotation.Repository; import io.micronaut.data.repository.CrudRepository; import java.util.List; @Repository public interface StudentRepository extends CrudRepository<Student, Long> { List<Student> findByName(String name); } |
You don’t need to write any query!
Micronaut will automatically generate this at compile time.
π§ Table Creation
If youβre using H2 or PostgreSQL/MySQL with Flyway or Liquibase (covered in a later post), tables can be automatically created based on entities or migrations.
For testing with H2, Micronaut can auto-create tables:
1 2 3 4 5 6 7 8 9 |
jpa: default: properties: hibernate: hbm2ddl: auto: update |
β For production, always use migrations instead of auto-DDL.
β Quick Test with Service Layer
You can now inject the repository in your services:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.kscodes.micronaut.school.services; import com.kscodes.micronaut.school.entities.Student; import com.kscodes.micronaut.school.repositories.StudentRepository; import jakarta.inject.Singleton; import java.util.List; @Singleton public class StudentService { private final StudentRepository studentRepository; public StudentService(StudentRepository studentRepository) { this.studentRepository = studentRepository; } public Student saveStudent(Student student) { return studentRepository.save(student); } public List<Student> getAllStudents() { return studentRepository.findAll(); } } |
π Common Issues
Problem | Solution |
---|---|
“Table not found” | Ensure database schema is created |
“Cannot find repository bean” | Check correct package scanning |
“NullPointerException” | Verify DI is properly configured |