A lite ORM Designed to reduce the stress you feel while leading with OracleDB.
Inspired by Sequelize and SequelizeTypescript
Please see change log to checkout new functions.
ChangeLog | TypeScript Demo App
Relax ORM depens on OracleDB instant client. Please follow the instruction. Official: OracleDB Client Install Guid
After installing the OracleDB client, run the script below on terminal.
npm i oracledb relax-orm -S
To create an Entity, you just extends Entity class and declare the generics type like example. Also you need to declare table name with @Table, one @PrimaryKey and Columns. Optionaly you can declare the use of sequence witch will be used on INSERT.
@Table('USER_TABLE')
export class User extends Entity<User>{
@PrimaryKey() // Each entity requires one PrimaryKey to use 'save' function
@Sequence('USER_SEQUENCE')
@Column('USER_ID')
id?: number;
@Column()
name?: string;
}
After creating Entities, you need to create and initialize connection and registering Entities.
const conn = new ConnectionManager({
user : DBCONFIG.user,
password : DBCONFIG.password,
connectString : DBCONFIG.connectString,
});
conn.addEntities([ User ]);
await conn.init();
Optionaly you can change oracledb config before creating ConnectionManager
ConnectionManager.config.maxRows = 100;
ConnectionManager.config.fetchAsString = [ oracledb.DATE, oracledb.NUMBER ];
const conn = new ConnectionManager({...You Connection Config});
After registering you can use the basic queries.
User.findAll()
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USE
*/
User.findAll( {where: { id: 1, name: 'walker' } });
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
WHERE SEQ_NUM_USER = :id$ AND NAME = :name$
*/
User.create({
id: 10, // If @Sequence is declared, this value will be ignored
name: 'walker'
})
/* Generates:
INSERT INTO RLXORM.TB_USER
( SEQ_NUM_USER, NAME )
VALUES ( RLXORM.SQ_USER.NEXTVAL, :name$ )
RETURNING SEQ_NUM_USER, NAME
INTO :out$id, :out$name
*/
// Saving entity
const user = User.findOne({ where: {id: 1} });
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
WHERE SEQ_NUM_USER = :id$
*/
user.name = 'style';
user.save();
/* Generates:
UPDATE RLXORM.TB_USER
SET SEQ_NUM_USER = :id$, NAME = :name$
WHERE SEQ_NUM_USER = :key$id
RETURNING SEQ_NUM_USER, NAME
INTO :out$id, :out$name
*/
User.destroy({
name: 'walker'
});
/* Generates: **NOTE** IT WILL DELETE RECORDS USING WHERE FILTER
DELETE FROM RLXORM.TB_USER WHERE NAME = :name$
*/
User.destroyAll();
/* Generates: **NOTE** IT WILL DELETE ALL RECORDS FROM TABLE
DELETE FROM RLXORM.TB_USER
*/
In findAll and findOne queries you can use options and combine them like examples below.
let res = await User.findAll({
where: {
[Op.or]: [
{ id: 10 },
{ id: 11 },
],
name: 'walker',
},
});
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
WHERE ( SEQ_NUM_USER = :id$ )
OR ( SEQ_NUM_USER = :id$ )
AND NAME = :name$
*/
res = await User.findOne({
where: {
[Op.and]: [
{ id: 10 },
{ name: 'walker' },
],
},
});
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
WHERE ( SEQ_NUM_USER = :id$ )
AND ( NAME = :name$ )
*/
res = await User.findAll({
order: [
[ 'id',ResultOrder.ASC ],
[ 'name',ResultOrder.DESC ]
]
});
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
ORDER BY SEQ_NUM_USER ASC, NAME DESC
*/
res = await User.findAll({
where: {
name: 'walker',
},
order: [
[ 'id',ResultOrder.ASC ],
[ 'name',ResultOrder.DESC ],
],
});
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM RLXORM.TB_USER
WHERE NAME = :name$
ORDER BY SEQ_NUM_USER ASC, NAME DESC
*/
res = await User.findAll({
limit: 2,
});
/* Generates:
SELECT SEQ_NUM_USER, NAME
FROM ( SELECT SEQ_NUM_USER, NAME, ROWNUM as TMP$ROWNUMBER
FROM RLXORM.TB_USER )
WHERE TMP$ROWNUMBER <= :TMP$LIMIT
*/
res = await User.findAll({
limit: 2,
order: [['name', ResultOrder.ASC]],
});
/* Generates: it uses ROW_NUMBER function with over to use ordered result
SELECT SEQ_NUM_USER, NAME
FROM ( SELECT SEQ_NUM_USER, NAME, ROW_NUMBER()
OVER ( ORDER BY NAME ASC ) as TMP$ROWNUMBER
FROM RLXORM.TB_USER ORDER BY NAME ASC )
WHERE TMP$ROWNUMBER <= :TMP$LIMIT
*/
res = await User.findAll({
order: [['id', ResultOrder.ASC]],
offset: 1,
limit: 2,
});
/* Genarates
SELECT SEQ_NUM_USER, NAME
FROM ( SELECT SEQ_NUM_USER, NAME, ROW_NUMBER()
OVER ( ORDER BY SEQ_NUM_USER ASC ) as TMP$ROWNUMBER
FROM RLXORM.TB_USER ORDER BY SEQ_NUM_USER ASC )
WHERE TMP$ROWNUMBER > :TMP$OFFSET
AND TMP$ROWNUMBER <= :TMP$LIMIT
*/
res = await User.findAll({
where: {
[Op.or]: [
{ id: { [Op.in]: [1, 2] } },
{ name: 'walker' },
],
},
});
/* Generates
SELECT SEQ_NUM_USER, NAME FROM RLXORM.TB_USER
WHERE ( SEQ_NUM_USER IN ( :id$in$0, :id$in$1 ) )
OR ( NAME = :name$ )
*/