Skip to content

Persisted getter properties #3936

@dkeleee

Description

@dkeleee

Consider an entity that defines a getter. The getter uses other properties to return a result.

Simple example:

@Entity()
class Test {
  @PrimaryKey()
  id!: number;

  @Property()
  value!: number;

  @Property({ persist: true })
  get doubleValue(): number {
    return this.value * 2;
  }
}

I would like to have an option that makes doubleValue have the following features:

  • it returns the correct value immediately after value is updated, without flushing
  • it can be used as a filter when querying for entities
  • it can be indexed

The simplest solution seems to be to always use the getter value in application code and to persist it to the database to make it useable in queries.

The code above seems to save the getter value on first insert and then exclusively uses the database value. This is described in #2760.

const test = new Test();
test.value = 5;
em.persist(test);
await em.flush();

console.log(test.doubleValue); // "10"
test.value = 7;
console.log(test.doubleValue); // "10", but "14" is expected

Considered alternatives:

@Property({ onUpdate: (e) => e.value * 2 }) and @Formula()
Both won't return the correct doubleValue after value is updated but before a flush.

A potential alternative solution would be to allow a @Formula() to be combined with a getter.
The formula snippet would be used inside SQL queries and the getter would be used inside application code.
Nothing would be persisted.

This feature exists in SQLAlchemy:
https://docs.sqlalchemy.org/en/20/orm/extensions/hybrid.html#defining-expression-behavior-distinct-from-attribute-behavior

The downside of this approach is that some operations that can be written in application code might not be possible to represent with SQL.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions