DEV Community

anand jaisy
anand jaisy

Posted on

JPA entity relationship with Micronaut data JDBC

What Is Micronaut

Micronaut is a JVM-based framework for building lightweight, modular applications. Micronaut is the latest framework designed to make creating microservices quick and easy.

Micronaut Data

Micronaut Data is 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.

JDBC

Micronaut Data JDBC is designed for users who prefer a lower-level experience and working directly with SQL.

Quick Start

Creating an application with the CLI

$ mn create-app --lang java example --features data-jdbc,flyway,mysql,jdbc-hikari
Enter fullscreen mode Exit fullscreen mode

The generated application will have a compile-scoped dependency on the micronaut-data-jdbc module and will use MySQL since we passed the mysql feature adding dependency on the JDBC driver for MySQL:

implementation("io.micronaut.data:micronaut-data-jdbc")
Enter fullscreen mode Exit fullscreen mode

You should also ensure you have the JDBC driver and connection pool dependencies configured:

runtimeOnly("io.micronaut.sql:micronaut-jdbc-hikari")
Enter fullscreen mode Exit fullscreen mode

The annotation processor needs to have the Micronaut Data processor dependency properly setup to enable compile-time generation and evaluation:

annotationProcessor("io.micronaut.data:micronaut-data-processor")
Enter fullscreen mode Exit fullscreen mode

Next up you need to configure at least one data source. The following snippet from the application configuration file is an example of configuring the default JDBC data source:

datasources.default.url=jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
datasources.default.driverClassName=org.h2.Driver
datasources.default.username=sa
datasources.default.password=
datasources.default.schema-generate=CREATE_DROP
datasources.default.dialect=H2
entity.prefix=demo_
entity.name=Entity1
Enter fullscreen mode Exit fullscreen mode

We will leverage JPA's robust capabilities for SQL schema generation by utilizing JPA entities in conjunction with Micronaut Data JDBC.

To use JPA annotations in the javax.persistence package use:

compileOnly("jakarta.persistence:jakarta.persistence-api")
Enter fullscreen mode Exit fullscreen mode

If you want to use JPA annotations in your entities with Micronaut Data JDBC, we strongly recommend you use jakarta.persistence annotations. Micronaut Data will remove support for javax.persistence annotations in the future.

Let's create an Job entity with a JPA annotation

@AllArgsConstructor
@Setter
@Getter
@Entity
public final class Job {
        @Id
        @GeneratedValue
        private UUID id;

        @NotNull
        private String title;

        @Column(columnDefinition = "TEXT")
        private String Description;

        @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE")
        private Instant startDate;

        @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE")
        private Instant endDate;
}
Enter fullscreen mode Exit fullscreen mode

We have another entity as Tag

@AllArgsConstructor
@Setter
@Getter
@Entity
public final class Tag {

    @Id
    @GeneratedValue
    private UUID id;    

    @NonNull
    @NotBlank
    @Column(unique = true, length = 255, name = "name")
    private String name;

    @Column(columnDefinition = "TEXT")
    private String description;

}
Enter fullscreen mode Exit fullscreen mode

A job can be associated with multiple tags, and each tag can be linked to multiple jobs. Consequently, the relationship from a job's perspective is a One-To-Many association (one job can have many tags), while from a tag's perspective, it is also a One-To-Many association (a tag can be associated with many jobs).

Image description

JPA Hibernate facilitates defining relationships between entities using JPA annotations. We will utilize these annotations to map the relationship between the Job and Tag entities.

@OneToMany

In JPA, the @OneToMany annotation is used to define a one-to-many relationship between two entities. It indicates that a single entity (the "one" side) is associated with multiple instances of another entity (the "many" side).

Key Features of @OneToMany:

  1. Owning Entity: The entity annotated with @OneToMany is the parent or owning entity in the relationship.

  2. Mapped By: The mappedBy attribute specifies the field in the child entity that maps back to the parent entity. It helps establish bidirectional relationships.

  3. Cascading: The cascade attribute allows operations such as persist, merge, or remove to propagate from the parent to the associated child entities.

  4. Fetching Strategy: The fetch attribute determines whether the related entities are loaded eagerly (FetchType.EAGER) or lazily (FetchType.LAZY).

@ManyToOne

In JPA, the @ManyToOne annotation is used to define a many-to-one relationship between two entities. It signifies that many instances of the referencing entity are associated with one instance of the referenced entity. This annotation is commonly used to represent the "many" side in a relationship.

Key Features of @ManyToOne:

  1. Owning Side: The entity annotated with @ManyToOne is the owning side of the relationship. It contains the foreign key column that establishes the link.
  2. Foreign Key: The @JoinColumn annotation is often used alongside @ManyToOne to specify the foreign key column name in the database.
  3. Cascading: The cascade attribute enables cascading operations such as persist, merge, or remove between the associated entities.
  4. Fetching Strategy: The fetch attribute determines whether the related entity is loaded eagerly (FetchType.EAGER) or lazily (FetchType.LAZY).

Let's create another entity as JobTag to hold the relationships between Job and Tag Entities

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public final class JobTag extends AuditTrail{

    @Id
    @GeneratedValue
    private UUID id; 
}
Enter fullscreen mode Exit fullscreen mode

Next, we will define the relationships among the entities. From the perspective of the Job entity, a single job can be associated with multiple tags. To represent this relationship, we will update the Job entity using the @OneToMany JPA annotation.

@AllArgsConstructor
@Builder
@Setter
@Getter
@Entity
public final class Job {
    // Other fields
        @OneToMany(mappedBy = "job", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
        private Collection<JobTag> jobTag = new ArrayList<>();
}
Enter fullscreen mode Exit fullscreen mode
@AllArgsConstructor
@Builder
@Setter
@Getter
@Entity
public final class Tag extends AuditTrail {

    // Other properties

    @OneToMany(mappedBy = "tag", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private Collection<JobTag> jobTag = new ArrayList<>();

}
Enter fullscreen mode Exit fullscreen mode

From the Tag entity perspective, a single tag can be associated with many jobs. To represent this relationship, we will update the JobTag entity using the @ManyToOne JPA annotation.

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public final class JobTag extends AuditTrail{

    @ManyToOne
    @JoinColumn(name = "job_id")
    private Job job;

    @ManyToOne
    @JoinColumn(name = "tag_id")
    private Tag tag;
}
Enter fullscreen mode Exit fullscreen mode

It is recommended to use Flyway or LiquidBase to run the migration in production.

Upon executing the migration, the defined relationships should be reflected in the corresponding database tables.

Top comments (0)