Skip to content

Entities and persistence

Persistence is decorator-driven on both languages. A class annotated @Entity becomes a managed table; the platform handles DDL emission, mapping, and CRUD.

How it works

  • TypeScript - data-store reflects *Entity.ts decorators into Hibernate HBM XML at synchronization time.
  • Java - data-store-java reflects @Entity Java annotations into the same HBM XML. Hibernate runs in dynamic-map mode - session.save(entityName, Map<String, Object>) rather than typed beans - so it never has to load the user's class across classloaders. EntityBeanMapper handles bean ↔ map conversion respecting @Column and @Transient.

Both paths end up in the same Hibernate SessionFactory, rooted at the default user-data datasource (not SystemDB).

Field annotations

AnnotationPurpose
@IdPrimary key field.
@GeneratedValue(strategy = GenerationType.SEQUENCE)Auto-generated PK (AUTO, IDENTITY, SEQUENCE, TABLE, UUID).
@Column(name=..., length=..., nullable=...)Column mapping override.
@TransientSkip the field during persistence.
@CreatedAtAuto-populated with the current timestamp on insert.
@UpdatedAtAuto-populated on every update.
@CreatedByAuto-populated with UserFacade.getName() on insert.
@UpdatedByAuto-populated with UserFacade.getName() on update.
@Documentation("...")Free-text description; surfaces in OpenAPI.

Defining an entity

Java

java
package demo;

import org.eclipse.dirigible.sdk.db.Column;
import org.eclipse.dirigible.sdk.db.Entity;
import org.eclipse.dirigible.sdk.db.GeneratedValue;
import org.eclipse.dirigible.sdk.db.GenerationType;
import org.eclipse.dirigible.sdk.db.Id;
import org.eclipse.dirigible.sdk.db.Table;
import org.eclipse.dirigible.sdk.platform.Documentation;

@Entity
@Table(name = "SAMPLE_COUNTRY")
@Documentation("Sample Country Entity")
public class Country {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "COUNTRY_ID")
    @Documentation("Auto-generated primary key")
    public Long id;

    @Column(name = "COUNTRY_CODE2", length = 2)
    public String code2;

    @Column(name = "COUNTRY_CODE3", length = 3)
    public String code3;

    @Column(name = "COUNTRY_NAME", length = 128)
    @Documentation("Official short name")
    public String name;
}

TypeScript / JavaScript

ts
import { Entity, Table, Id, Generated, Column } from "@aerokit/sdk/db/decorators";

@Entity("Country")
@Table("SAMPLE_COUNTRY")
export class Country {

  @Id()
  @Generated("sequence")
  @Column({ name: "COUNTRY_ID", type: "long" })
  public id?: number;

  @Column({ name: "COUNTRY_NAME", type: "string" })
  public name?: string;
}

Repository pattern

The recommended pattern is to subclass JavaRepository<T> (Java) or Repository<T> (TypeScript). Both deliver typed CRUD plus findAll, findById, save, update, delete, deleteById, count, and query/HQL out of the box.

Java

@Repository registers the class as a singleton; JavaRepository<T> is the typed CRUD base:

java
import org.eclipse.dirigible.sdk.component.Repository;
import org.eclipse.dirigible.components.data.store.java.repository.JavaRepository;

@Repository
public class CountryRepository extends JavaRepository<Country> {

    public CountryRepository() {
        super(Country.class);
    }
}

Controllers inject the repository - constructor injection is preferred - and call typed methods directly, with no JavaEntityStore and no BeanProvider:

java
@Controller
public class CountryController {

    private final CountryRepository countries;

    public CountryController(CountryRepository countries) {
        this.countries = countries;
    }

    @Get("/")        public List<Country> list()                          { return countries.findAll(); }
    @Get("/{id}")    public Country       byId(@PathParam("id") Long id)  { return countries.findById(id); }
    @Post            public Country       create(@Body Country c)         { return countries.save(c); }
    @Delete("/{id}") public void          remove(@PathParam("id") Long id) { countries.deleteById(id); }
}

Field @Inject on the repository works too; see Dependency injection. Working sample: dirigiblelabs/sample-java-entity-decorators.

TypeScript / JavaScript

Repository<T> is auto-generated; subclass it via @Component:

ts
import { Repository } from "@aerokit/sdk/db";
import { Component } from "@aerokit/sdk/component";
import { Country } from "./Country";

@Component("CountryRepository")
export class CountryRepository extends Repository<Country> {
  constructor() {
    super(Country);
  }
}

See also

Released under the EPL-2.0 License.