@themost/jspa v2.0.0

@themost/jspa
@themost web framework JavaScript Persistent API on top of @themost/data ORM.
@themost/jspa is a mimic of Java Persistent API for Node.js environment and provides a set of tools for describing object relational mapping.
The following example describes a Thing class:
import { DataObject } from '@themost/data';
import { Column, Entity, GeneratedValue, GenerationType, Id, Table, Counter, Basic, Formula, ManyToOne, FetchType, ColumnDefault } from '@themost/jspa';
@Entity()
@Table()
class Thing extends DataObject {
constructor() {
super();
}
@Id()
@Column()
@GeneratedValue({
strategy: GenerationType.Identity
})
public id?: Counter;
@Basic()
public name?: string;
@Column()
public alternateName?: string;
@Column()
public description?: string;
@Column()
public additionalType?: string;
@Column()
public sameAs?: string;
@Column()
public url?: string;
@Column()
public identifier?: string;
@Column()
public image?: string;
@Column({
nullable: false,
updatable: false
})
@ColumnDefault(() => new Date())
public dateCreated?: Date;
@Column({
nullable: false
})
@Formula(() => new Date())
public dateModified?: Date;
@Column({
nullable: true,
updatable: false,
type: 'User'
})
@ManyToOne({
fetchType: FetchType.Lazy
})
public createdBy?: any;
@Column({
nullable: true,
type: 'User'
})
@ManyToOne({
fetchType: FetchType.Lazy
})
public modifiedBy?: any;
}
export {
Thing
}Usage
npm i @themost/jspaAnnotations
@Entity
The basic annotation of a class. Use optional @Entity.name attribute to define the name of this entity if it's different than class name and @Entity.version attribute to allow @themost/data auto-upgrade operations to update database objects after any change.
@Entity({
version: '1.0.0'
})
class Party extends Thing {
...
}@Entity() annotation includes @Entity.privileges attribute to allow setting the collection of default privileges assigned to a class
@Entity({
version: '1.0.0',
privileges: [
{
mask: 15,
type: 'global'
},
{
mask: 15,
type: 'global',
account: 'Administrators'
}
]
})
class Party extends Thing {
...
}The previous example defines that Party will be accessible by each user which has permissions defined in data permission storage. It also defines that Administrators have full-access by default.
@Table
The optional @Table annotation allows you to specify the properties of the database objects that will be used to persist the entity in the database.
@Entity({
version: '1.0.0'
})
@Table(
name: 'PartyBase'
)
class Party extends Thing {
...
}@Table.name
The name of the table that will be used to persist objects. The default value provided by
@themost/datais a concatenation of entity's name and word "Base" e.g.PartyBase,PostalAddressBaseetc.@Table.indexes
A collection of indexes that should be included while creating or updating database objects.
@Table( indexes: [ { columnList: [ 'name' ] }, { columnList: [ 'email' ] } ] ) class Party extends Thing { ... }@Table.uniqueConstraints
A collection of unique constraints that should be included while creating or updating database objects based on database engine features.
@Table( uniqueConstraints: [ { columnNames: [ 'email' ] } ] ) class Party extends Thing { ... }
@Column
@Column annotation is used to specify the mapped column for a property
@Entity()
@Table()
class Thing extends DataObject {
...
@Column()
public name?: string;
}@Column.name
(Optional) A string which defines the column name. If
@Column.nameis missing property name is being used.class Thing extends DataObject { ... @Column({ name: 'obj_name' }) public name?: string; }@Column.nullable
(Optional) A boolean which indicates whether the mapped column is nullable of false. The default value is true.
@Column.type
A string which defines the type of the column. Column may be one of the primitive column types of
@themost/dataor an object typeclass Thing extends DataObject { ... @Column({ type: ColumnType.Text }) public name; @Column({ type: 'User' }) public createdBy; }@Column.length
(Optional) The column length
class Thing extends DataObject { ... @Column({ type: ColumnType.Text, length: 100 }) public name; }@Column.scale
(Optional) The scale for a numeric column
@Column.precision
(Optional) The precision for a numeric column
@Column.insertable
(Optional) A boolean which indicates whether the column will be included while inserting objects or not
@Column.updatable
(Optional) A boolean which indicates whether the column will be included while updating objects or not
@Id()
@Id is used to specify identity columns
@Entity()
@Table()
class Thing extends DataObject {
@Id()
@Column({
type: ColumnType.Counter
})
@GeneratedValue({
strategy: GenerationType.Identity
})
public id;
...
}@GeneratedValue()
@GeneratedValue annotation is used to specify generation strategy for identity columns
@Entity()
@Table()
class Thing extends DataObject {
@Id()
@Column({
type: ColumnType.Counter
})
@GeneratedValue({
strategy: GenerationType.Identity
})
public id;
...
}The available generation strategies are:
GenerationType.Auto: Based on the database’s support for primary key generation framework decides which generator type to be used.GenerationType.Identity: In this case database is responsible for determining and assigning the next primary key.GenerationType.Sequence: A sequence specify a database object that can be used as a source of primary key values.GenerationType.Table: It keeps a separate table with the primary key values
@Formula
@Formula annotation is used to specify calculated values.
class Thing extends DataObject {
...
@Formula((event) => {
const context = event.context as any;
let user: { name?: string } =context.interactiveUser;
if (user && user.name) {
return {
name: user.name
};
}
user = context.user;
if (user && user.name) {
return {
name: user.name
};
}
return null;
})
public createdBy?: any;
}@Formula closure has event parameter of type FormulaArgs
FormulaArgs.contextThe current data contextFormula.modelAn instance ofDataModelclass which represents the current entity typeFormula.targetThe current object
@ColumnDefault
@ColumnDefault annotation defines the default value of the mapped column
@Entity()
@Table()
class Thing extends DataObject {
...
@ColumnDefault(() => new Date())
public dateCreated?: Date;
}@ColumnDefault can be a simple closure which returns a single value or a closure which has event parameter of type ColumnDefaultArgs
ColumnDefaultArgs.contextThe current data contextColumnDefaultArgs.modelAn instance ofDataModelclass which represents the current entity typeColumnDefaultArgs.targetThe current object
@Embedded
@Embedded annotation is used to embed type into another type. An embedded type will be inserted, updated or deleted as result of an operation made on parent object.
@Entity()
class Place extends Thing {
...
@Embedded()
public address?: PostalAddress;
}e.g. Place entity type embeds PostalAddress into address property.
@ManyToOne
@ManyToOne annotation defined a foreign-key association between two entity types
@Entity()
class Party extends Thing {
...
@Column({
nullable: false,
updatable: false,
type: 'User'
})
@ManyToOne({
fetchType: FetchType.Lazy
})
public createdBy?: User;
}e.g. Party.createdBy defines a foreign-key association between Party and User
@ManyToOne.optionalA boolean which whether the association is optional or not.@ManyToOne.fetchTypeDefines that data can be lazily or eagerly fetched
@OneToMany
@OneToMany annotation is used to implement one-to-many relationship between two entity types.
@Entity()
class Place extends Thing {
...
@OneToMany({
cascadeType: CascadeType.Detach,
fetchType: FetchType.Lazy,
mappedBy: 'containedIn',
targetEntity: 'Place'
})
public containsPlace?: Place;
}e.g. Place has a collection of places based on property containedIn
@OneToMany annotation has the following properties
@ManyToOne.fetchTypeDefines that data can be lazily or eagerly fetched@ManyToOne.cascadeTypeDefines the cascade operation that will be used while removing an object.@ManyToOne.mappedByThe target column that holds the association between the current entity type and the target entity type.@ManyToOne.targetEntityThe type of the target entity
@ManyToMany
@OneToMany annotation is used to implement many-to-many relationship between two entity types.
class Group extends Account {
...
@ManyToMany({
targetEntity: 'Account',
fetchType: FetchType.Lazy,
cascadeType: CascadeType.Detach
})
@JoinTable({
name: 'GroupMembers',
joinColumns: [
{
name: 'object',
referencedColumnName: 'id'
}
],
inverseJoinColumns: [
{
name: 'value',
referencedColumnName: 'id'
}
]
})
public members?: Account[];
...
}e.g. Every Group has a collection of members of type Account
@ManyToOne annotation has the following properties
@ManyToOne.fetchTypeDefines that data can be lazily or eagerly fetched@ManyToOne.cascadeTypeDefines the cascade operation that will be used while removing an object.@ManyToOne.targetEntityThe type of the target entity
The @JoinTable annotation is being used to define the database object where this relationship will be stored. @JoinTable.joinColumns contains the local property and @JoinTable.inverseJoinColumns contains the foreign property.
e.g. Group.members many-to-many association will be stored in GroupMembers table where GroupMembers.object column will be a Group.id and GroupMembers.value column will be an Account.id.
@ElementCollection
@ElementCollection annotation is used to define a collection of primitive typed values e.g. an array of strings or numbers.
class Account extends Thing {
...
@ManyToMany({
targetClass: Text,
fetchType: FetchType.Lazy
})
@CollectionTable({
name: 'AccountTags',
joinColumns: [
{
name: 'object',
referencedColumnName: 'id'
}
],
inverseJoinColumns: [
{
name: 'value'
}
]
})
tags;
...
}e.g. Every Account has a collection of tags of type Text which is a subclass of String
The @CollectionTable annotation is being used to define the database object where this relationship will be stored. @CollectionTable.joinColumns contains the local property and @CollectionTable.inverseJoinColumns may contain the column where each value will be stored.
e.g. Account.tags will be persisted in AccountTags table where object field contains Account.id and value field contains Account.tag value.
@EntityListeners
@EntityListeners annotation defines a collection of classes that contain procedures which are going to be executed before and after CRUD operations.
@Entity()
@EntityListeners(OnUserUpdateListener, OnUserRemoveListener, OnUserInitListener)
class User extends Account {
...
}e.g. OnUserUpdateListener contains PreUpdate and PostUpdate procedures
export class OnUserUpdateListener {
@PreUpdate()
async onPreUpdate(event: PreUpdateEvent) {
//
}
@PostUpdate()
async onPostUpdate(event: PostUpdateEvent) {
//
}
}@PreInit
@PreInit annotation defines an event which will be occured before creating or updating an entity type
@PreInit()
async onPreInit(event: PreInitEvent) {
//
}@PostInit
@PostInit annotation defines an event which will be occured after creating or updating an entity type
@PostInit()
async onPostInit(event: PostInitEvent) {
//
}@PreLoad
@PreLoad annotation defines an event which will be occured before loading an entity
@PreLoad()
async onPreLoad(event: PreLoadEvent) {
//
}@PostLoad
@PostInit annotation defines an event which will be occured after loading an entity
@PostLoad()
async onPostLoad(event: PostLoadEvent) {
//
}@PrePersist
@PreLoad annotation defines an event which will be occured before inserting an entity
@PrePersist()
async onPrePersist(event: PrePersistEvent) {
//
}@PostPersist
@PostPersist annotation defines an event which will be occured after inserting an entity
@PostPersist()
async onPostPersist(event: PostPersistEvent) {
//
}@PreUpdate
@PreUpdate annotation defines an event which will be occured before updating an entity
@PreUpdate()
async onPreUpdate(event: PreUpdateEvent) {
//
}@PostUpdate
@PostUpdate annotation defines an event which will be occured after updating an entity
@PostUpdate()
async onPostUpdate(event: PostUpdateEvent) {
//
}@PreRemove
@PreRemove annotation defines an event which will be occured before removing an entity
@PreRemove()
async onPreRemove(event: PreRemoveEvent) {
//
}@PostUpdate
@PostRemove annotation defines an event which will be occured after removing an entity
@PostRemove()
async onPostRemove(event: PostRemoveEvent) {
//
}