npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nbatis

v2.0.2

Published

It's a data persistence plugin on the node.js platform,it is similar to mybatis

Downloads

23

Readme

Welcome to NBatis2.0 !

This a node.js plugin about data persistence, if you used mybatis before, you'll learn it soon.. The plugin is given priority to with node mysql driver,at present. NBatis is mostly API compatible with mysql and supports majority of features. It also offers these additional features.


Table of contents


Install

npm install nbatis --save

Example

PS: It is recommended to use typescript to code your project. Make sure typescript is installed before this example. Please install the ts plug-in globally.

Create POJO
  • We can create a pojo class named UserSQL.ts. This class can help us to create test table in the database.
import { DBUtil } from 'nbatis';

export default class UserSQL {
    id:any;
    username:any;
    password:any;
    gender:any;
    birthday:any;
    email:any;
    url:any;
    createTime:any;
    constructor() {
        this.id = {
            type: 'int(11)',
            primary: true
        };
        this.username = {
            type: 'varchar(255)',
            notNull: true,
            default: '',
            value: ()=>DBUtil.randomString('w', 'm')
        };
        this.password = {
            type: 'varchar(255)',
            default: '',
            value: ()=>DBUtil.randomString('d', '', 6)
        };
        this.gender = {
            type: 'char(1)',
            notNull: true,
            default: '',
            value: ()=>DBUtil.randomValueFromList(['M','F'])
        }
        this.birthday = {
            type: 'Date',
            value: ()=>DBUtil.randomDateTimeString('1980-01-01', '2010-12-12', 'yyyy-MM-dd')
        };
        this.email = {
            type: 'varchar(255)',
            value: ()=>DBUtil.randomEmail()
        }
        this.url = {
            type: 'varchar(255)',
            value: ()=>DBUtil.randomDomain()
        }
        this.createTime = {
            type: 'DateTime',
            notNull: true,
            default: '#{NOW()}'
        };
    }
}
  • Each item in the table corresponds to each property of the pojo class, all of which are public and default value is a object. The object have several properties. These properties help us complete the SQL statement.
{
    type: '', //SQL data type, the type is string.
    primary: false, //To determine whether the property is a primary key, the type is boolean.
    notNull: false, //To determine whether the property is NOT NULL, the type is boolean.
    default: '', //SQL default value, the type is any.
    value: 0 //This property is used when bulk data is inserted. It can be of any type, most of the time it's a random function.
}
Create Unit Test Case
  • We use tunit which is a typescript unit test plugin here. First of all, to install tunit.
npm install tunit --save-dev
  • Second, create a entity class named FactoryTest.ts. Because a decorator in tunit is named Test so the name of the test class cannot be called "Test".
import path from 'path';
import { BeforeClass,Test,AfterClass,TUnit,Assert } from 'tunit';
import { SqlSessionFactory, DBUtil } from '../index';
import UserSQL from './UserSQL';

@TUnit('./')
export default class FactoryTest {
   factory:any
   session:any;
   constructor() {
       this.session = null;
       this.factory = null;
   }

   @BeforeClass
   async init(next:Function) {
       try {
           const configrationFilePath = path.join(__dirname, './nbatis_config.json');
           this.factory = new SqlSessionFactory().createPool(configrationFilePath);
           this.session = await this.factory.openSession();
           next();
       }
       catch(err) {
           next(err);
       }
   }
   /**
    * To test creating a table with the class.
    */
   @Test
   async createTable(next:Function) {
       const sql = DBUtil.createTableSQL(UserSQL);
       try {
           const res = await this.session.querySet(sql);
           next(res);
       }
       catch(err) {
           await this.session.rollback();
           next(err);
       }
   }
   /**
    * To test the method queryGet.
    */
   @Test
   async getTableDesc(next:Function) {
       const sql = 'desc user_sql';
       try {
           const res = await this.session.queryGet(sql);
           next(res);
       }
       catch(err) {
           next(err);
       }
   }
   /**
    * To test inserting random data in quantity.
    */
   @Test
   async batchInsert(next:Function) {
       const sql = DBUtil.batchInsertSQL(UserSQL, '', 10);
       try {
           const res = await this.session.querySet(sql);
           const assert = Assert.assertNotNull(res);
           next(res, assert);
       }
       catch(err) {
           this.session.rollback();
           next(err);
       }
   }
   /**
    * To test getting a list of data
    */
   @Test
   async selectList(next:Function) {
       try{
           const params = {
               start:0,
               length:5
           },
           res = await this.session.selectList('UserSQL.list', params),
           assert = Assert.assertNotNull(res);
           next(res, assert);
           
       }
       catch(err) {
           next(err);
       }
   }
   /**
    * To test getting a piece of data by id.
    */
   @Test
   async testSelectOne(next:Function){
       try{
           const params = {
               tableName: 'user_sql',
               id:1
           }
           const res = await this.session.selectOne('UserSQL.loadById', params);
           next(res);
       }
       catch(err) {
           next(err);
       }
   }
   /**
    * To test updating a piece of data
    */
   @Test
   async update(next:Function){
       try{
           const params = {
               id: 1,
               url:'www.test001.com'
           },
           res = await this.session.insert('UserSQL.updateById', params);
           next(res);
       }
       catch(err) {
           this.session.rollback();
           next(err);
       }
   }
   /**
    * To test dynamic sql commands
    */
   @Test
   async pager(next:Function) {
       try{
           const params = {
               tableName: 'user_sql',
               where: '"%com"',     //String variables in dynamic SQL need to be quoted.
               start:0,
               pageSize:5,
               order: 'desc'
           },
           res = await this.session.selectList('UserSQL.pager', params);
           next(res);
       }
       catch(err) {
           next(err);
       }
   }
   /**
    * To test deleting a piece of data
    */
   @Test
   async delete(next:Function){
       try{
           const res = await this.session.insert('UserSQL.deleteById', 10);
           next(res);
       }
       catch(err) {
           this.session.rollback();
           next(err);
       }
   }
   /**
    * To test multiple sql commands in one transaction, the sql commands must be modify instructions of table.
    */
   @Test
   async insertAndUpdate(next:Function){
       try{
           const params = {
               tableName:'user_sql',
               username:'test002',
               password:'123456',
               gender:'M',
               birthday:'1996-01-01',
               email:'[email protected]',
               url:'test.vys.cc',
               updatePassword:'654321'
           },
           res = await this.session.insert('UserSQL.insertAndUpdate', params);
           next(res);
       }
       catch(err) {
           this.session.rollback();
           next(err);
       }
   }
   /**
    * To test delete a table with the class
    */
   @Test
   async dropTabel(next:Function) {
       const sql = DBUtil.dropTableSQL(UserSQL);
       let res:any;
       try {
           res = await this.session.querySet(sql);
       }
       catch(err) {
           this.session.rollback();
           next(err);
       }
       finally {
           if(this.session) {
               await this.session.release();
           }
           next(res);
       }
   }
   /**
    * Test to close connection pool
    */
   @AfterClass
   async endPool(next:Function) {
       let res:any;
       try {
           res = await this.factory.endPool();
           next(res);
       }
       catch(err) {
           next(err);
       }
   }
}

Next we start configuring nbatis.

Configuration
  • Fist, to create a configuration file named nbatis_config.json,of course you can name it anyother name.

The configuration items are here:

{
    "dataSource": {
        "host": "your database address",
        "user": "your username",
        "password": "your password",
        "database": "your database name",
        "connectionLimit": 5
    },
    "mappers": {
        "UserSQL": "./user_mapper.json"
    }
}
  • Second, creating mapper file called user_mapper.json. If you have multiple mapper files, you can put them in one folder.
{
  "list": {
    "parameterType": "object",
    "sql": "select * from user_sql limit ${start},${length}"
  },
  "loadById": {
    "parameterType": "object",
    "sql": "select * from user_sql where id=${id}"
  },
  "pager": {
    "parameterType": "object",
    "dynamic": true,
    "sql": "select * from user_sql <%if({{where}}){return 'where url like ${where}'}%> <%if({{orderKey}}&&{{order}}){return 'order by ${orderKey} ${order}';}%> <%if({{start}}&&{{pageSize}}){return 'limit ${start},${pageSize}';}%>"
  },
  "updateById": {
    "parameterType": "object",
    "sql": "update user_sql set url=#{url} where id=#{id}"
  },
  "deleteById": {
    "parameterType": "number",
    "sql": "delete from user_sql where id=#{id};"
  },
  "insertAndUpdate": {
    "parameterType": "object",
    "sql": "insert into ${tableName} (username,password,gender,birthday,email,url) values (#{username},#{password},#{gender},#{birthday},#{email},#{url});update ${tableName} set password=#{updatePassword} where username=#{username}"
  }
}
  • Attribute Description:

| Property | Description | | ------------- |:-------------| | parameterType| Javascript basic data type: number, string, boolean, object; the type is string| | dynamic|Whether the SQL statement is dynamic, the type is boolean or undefined| | sql|SQL statements with variables, the type is string|

Run
  • Make sure the typescript configuration file tsconfig.json is generated before running.
tsc --init 
  • For now, you can run the unit test case.
ts-node ./TheTest.ts

If you set a path in the decorator TUnit, the tunit.log file will be generated at the end of the test under that path. The resulting log is written to the file as an addendum.

Common SQL

Description of non-dynamic SQL statements in mapper files

| Symbol | Description | | ------------- |:-------------| | ${} |The program will put ${} replaced with parameter values| | #{} |The program will put #{} replaced with ?, escaping-query-values|

Dynamic SQL

You can write SQL statements as normal js syntax, allowing the SQL statements to produce different results as parameters.

| Symbol | Description | | ------------- |:-------------| |<%%>|javascript code is included between symbols| |{{params}}|The SQL parameters that appear in the javascript statement are wrapped in {{}}|

Multiple SQL

  • If you want to multiple operations in one transaction, you can join multiple sql commands with semi-colon.

All statements must be modify the statement for the table.

Here is a example:

"insert into ${tableName} (username,password,gender,birthday,email,url) values (#{username},#{password},#{gender},#{birthday},#{email},#{url});update ${tableName} set password=#{updatePassword} where username=#{username}"

Multiple SQL runs can also manipulate multiple tables.

Template SQL

  • The class SqlSessionTemplate is used here, which is SqlSessionFactory wrapper class. Its main function is to simplify the operation of getting session, session release. The user takes the session out of the template and does not care about about error fallback or session release.
import path from 'path';
import { BeforeClass,Test,AfterClass,TUnit,Assert } from 'tunit';
import { SqlSessionTemplate, DBUtil } from '../index';
import UserSQL from './UserSQL';

@TUnit('./')
export default class TemplateTest {
    template:any
    constructor() {
        this.template = null;
    }
    @BeforeClass
    async init(next:Function) {
        try {
            const configrationFilePath = path.join(__dirname, './nbatis_config.json');
            this.template = new SqlSessionTemplate(configrationFilePath);
            next();
        }
        catch(err) {
            next(err);
        }
    }
    @Test
    async createTable(next:Function) {
        const sql = DBUtil.createTableSQL(UserSQL);
        try {
            const res = await this.template.querySet(sql);
            next(res);
        }
        catch(err) {
            next(err);
        }
    }
    @Test
    async batchInsert(next:Function) {
        const sql = DBUtil.batchInsertSQL(UserSQL, '', 10);
        try {
            const res = await this.template.querySet(sql);
            const assert = Assert.assertNotNull(res);
            next(res, assert);
        }
        catch(err) {
            next(err);
        }
    }
    @Test
    async selectList(next:Function) {
        try{
            const params = {
                start:0,
                length:5
            },
            res = await this.template.selectList('UserSQL.list', params),
            assert = Assert.assertNotNull(res);
            next(res, assert);
        }
        catch(err) {
            next(err);
        }
    }
    @Test
    async insertAndUpdate(next:Function){
        try{
            const params = {
                tableName:'user_sql',
                username:'test002',
                password:'123456',
                gender:'M',
                birthday:'1996-01-01',
                email:'[email protected]',
                url:'test.vys.cc',
                updatePassword:'654321'
            },
            res = await this.template.insert('UserSQL.insertAndUpdate', params);
            next(res);
        }
        catch(err) {
            next(err);
        }
    }
    @Test
    async dropTabel(next:Function) {
        const sql = DBUtil.dropTableSQL(UserSQL);
        let res:any;
        try {
            res = await this.template.querySet(sql);
            next(res);
        }
        catch(err) {
            next(err);
        }
    }
    @AfterClass
    async endPool(next:Function) {
        try {
            const res = await this.template.getFactory().endPool();
            next(res);
        }
        catch(err) {
            next(err);
        }
    }
}
  • Let's use TemplateTest.ts as an example and it looks a little bit like FactoryTest.ts. Each of these operations takes an session from the connection pool, and template automatically releases session when the operation is complete. In case FactoryTest, it does all the work in one session, and the developer needs to be concerned about fallback and release.

SqlSessionTemplate is recommended for practical development.

API

[SqlSessionFactory]

createPool(configFilePath:string):any

Each factory object corresponds to a link pool object.

  • Parameters configFilePath: The path to the configuration file.

  • Return factory object.

openSession():Promise<any>
  • Return session.
getPool():any
  • Returns a singleton pool object.
endPool():Promise<any>
  • Close pool.

[Session / SqlSessionTemplate]

async selectList(tag:string, params:any):Promise<any>
  • Parameters tag: The key of item in mapper file. params: Parameters to pass.

  • Return a list of data.

async selectOne(tag:string, params:any):Promise<any>
  • Parameters tag: The key of item in mapper file. params: Parameters to pass.

  • Return a piece of data.

async insert(tag:string, params:any):Promise<any>
async update(tag:string, params:any):Promise<any>
async delete(tag:string, params:any):Promise<any>
  • Parameters tag: The key of item in mapper file. params: Parameters to pass.

  • Return a list of state object.

async queryGet(sql:string):Promise<any>
  • Parameters sql: SQL statement

  • Return the query results.

async querySet(sql:string):Promise<any>
  • Parameters sql: SQL statement

  • Return a list of state object.

[SqlSessionTemplate]

getFactory():any
  • Return a factory object.

[DBUtil]

static createTableSQL(typeReference:any, tableName?:string):string
  • Parameters typeReference: Class. tableName: Table name.

  • Return sql statement.

static batchInsertSQL(typeReference:any, tableName?:string, dataNumber?:number):string
  • Parameters typeReference: Class. tableName: Table name. dataNumber: The amount of data inserted.

  • Return sql statement.

static dropTableSQL(params:any):string
  • Parameters params: Class or table name.

  • Return sql statement.

static randomString(tag:string, letterCase?:string, len?:number):string
  • Parameters tag: String content, 'w':alphanumeric; 'c':pure letters; 'd': pure numbers. letterCase: Case mark, 'l':lowercase; 'b':uppercase; 'm':case mixing. len: The length of string.

  • Return a random string.

static randomDateTimeString(startDate?:string, endDate?:string, returnFormat?:string):string
  • Parameters startDate: Start date, the default value is '1970-01-01'. endDate: End date, the default value is now. returnFormat: The length of string.

  • Returns the format of the datetime string, the format is 'yyyy-MM-dd' or 'hh:mm:ss' or 'yyyy-MM-dd hh:mm:ss'.

static randomValueFromList(dataList:Array<any>):string
  • Parameters dataList: A list.

  • Returns a random value in the array.

static randomEmail():string
  • Returns a random email.
static randomDomain(isSubDomain?:boolean):string
  • Parameters isSubDomain: Determines whether the sub-domain name is generated. if true return 'xxx.domain.com' else 'www.domain.com'

  • Returns a random domain name.

static birthdayToAge(birthday:string):number
  • Parameters birthday: Datetime string, the format is '1970-01-01'

  • Return age.

More specifications, in the building...

NPM