Beginner Tutorial - Filter

Introduction

This provider is to provide DAO for FineDB, the built-in database of FineReport. With this, we can store our data generated during the plugin lifecycle into the database.

package com.fr.db.fun;

import com.fr.plugin.db.accessor.DBAccessible;
import com.fr.stable.fun.mark.Mutable;

/**
 * For a plugin to register custom tables
 */
public interface DBAccessProvider extends Mutable, DBAccessible {

    String XML_TAG = "DBAccessProvider";

    int CURRENT_LEVEL = 1;
}

The methods of DBAccessProvider are inherited from DBAccessible and DBInjectable:

package com.fr.plugin.db.accessor;

import com.fr.stable.db.dao.DAOProvider;

public interface DBAccessible extends DBInjectable {
    DAOProvider[] registerDAO();
}
package com.fr.plugin.db.accessor;

import com.fr.stable.db.accessor.DBAccessor;

public interface DBInjectable {
    void onDBAvailable(DBAccessor dbAccessor);
}

DBAccessProvider#registerDAO: to register custom DAO, the main method to be focused on.

DBAccessProvider#onDBAvailable:to do some initialization with DBAccessor.

To register the provider:

<extra-core>
    <DBAccessProvider class="com.fr.plugin.dao.DemoDBAccessProvider"/>
</extra-core>

Register a table and DAO

The resigterDAO method mentioned above returns an array of DAOProvider. Below is DAOProvider:

package com.fr.stable.db.dao;

import com.fr.stable.db.entity.BaseEntity;

public interface DAOProvider<T extends BaseEntity> {

    Class<T> getEntityClass();

    Class<? extends BaseDAO<T>> getDAOClass();
}

DAOProvider#getEntityClass: to get an entity that describes the structure of a table.

DAOProvider#getDAOClass: to get a class that implements the detailed data operation to a table.

Entity

Declare the structure of a table with annotation. In most cases, we extend BaseEntity, which already includes the 'id' column, to add our columns.

@Entity: to declare the class as an entity.

@Table: to declare the table mapped with this clas. The attribute 'name' is to set the table name.

@Column: to declare the mapping between the property and the field.

Commonly used attributes:

Attribute Description Default
name the field name empty
unique whether the field value must be unique false
nullable whether the null value is acceptable true
length the maximum length of the value 255
precision the number of digits when the field type is Number 0
scale the number of decimals when the field type is Number 0

Here is a demo for an Entity:

package com.fr.plugin.dao;

import com.fr.stable.db.data.DataRecord;
import com.fr.stable.db.entity.BaseEntity;
import com.fr.third.javax.persistence.Column;
import com.fr.third.javax.persistence.Entity;
import com.fr.third.javax.persistence.Table;

@Entity
@Table(name = "fine_plugin_demo")
public class DemoEntity extends BaseEntity {
    @Column(name="name")
    private String name;
    @Column(name="value")
    private String value;
    @Column(name="num",precision = 10,scale = 2)
    private double num;

    public void setName(String name) {
        this.name = name;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public String getValue() {
        return value;
    }

    public double getNum() {
        return num;
    }
    public void setNum(double num) {
        this.num = num;
    }
}

DAO

package com.fr.plugin.dao;

import com.fr.stable.db.dao.BaseDAO;
import com.fr.stable.db.session.DAOSession;

public class DemoDao extends BaseDAO<DemoEntity> {
    public DemoDao(DAOSession daoSession) {
        super(daoSession);
    }

    @Override
    protected Class<DemoEntity> getEntityClass() {
        return DemoEntity.class;
    }
}

Register the table and DAO defined

@Override
public DAOProvider[] registerDAO() {
    return new DAOProvider[]{new DAOProvider() {
        @Override
        public Class getEntityClass() {
            return DemoEntity.class;
        }
        @Override
        public Class<? extends BaseDAO> getDAOClass() {
            return DemoDao.class;
        }
    }};
}

Database Access Implementation

For now, we have implemented the registration of our table and DAO. The next thing is to define how to access the table and do CRUD.

First, let's look at the defined DBAccessProvider:

public class DemoDBAccessProvider extends AbstractDBAccessProvider {
    private static DBAccessor dbAccessor = null;
    public static DBAccessor getDbAccessor() {
        return dbAccessor;
    }
    @Override
    public DAOProvider[] registerDAO() {
        return new DAOProvider[]{new DAOProvider() {
            @Override
            public Class getEntityClass() {
                return DemoEntity.class;
            }
            @Override
            public Class<? extends BaseDAO> getDAOClass() {
                return DemoDao.class;
            }
        }};
    }

    @Override
    public void onDBAvailable(DBAccessor dbAccessor) {
        DemoDBAccessProvider.dbAccessor=dbAccessor;
    }
}

Generally, we use DBAccessor to do access the database and do data operation. The methods are:

runQueryAction: to query data (without transaction).

runDMLAction: to add/delete/update data (with transaction).

The arguments for these methods are DBAction:

package com.fr.stable.db.action;

import com.fr.stable.db.dao.DAOContext;

public interface DBAction<T> {
    T run(DAOContext daoContext) throws Exception;
}

Data Query

This is a demo of how to query data from the table defined in DemoEntity:

try {
    List<DemoEntity> values  =  DemoDBAccessProvider.getDbAccessor().runQueryAction(new DBAction<List<DemoEntity>>() {
        @Override
        public List<DemoEntity> run(DAOContext daoContext) throws Exception {
            daoContext.getDAO(DemoDao.class).find(QueryFactory.create().addRestriction(RestrictionFactory.eq("name", "Joe")));
            return null;
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}

The argument of find() is of QueryCondition type. We can define the query condition or restriction with it.

QueryCondition queryCondition= QueryFactory.create();
queryCondition.setCount(1);
queryCondition.setSkip(1);
queryCondition.addRestriction(RestrictionFactory.eq("num",1111.45));
queryCondition.addGroupBy("id");
queryCondition.addSort("name");

Data Modification

Add record:

try {
      DemoDBAccessProvider.getDbAccessor().runDMLAction(new DBAction<DemoEntity>() {
        @Override
        public DemoEntity run(DAOContext daoContext) throws Exception {
            DemoEntity entity=new DemoEntity();
            entity.setId(UUID.randomUUID().toString());
            entity.setName("Joe");
            entity.setNum(123);
            daoContext.getDAO(DemoDao.class).add(entity);
            return null;
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}

Delete record:

try {
    DemoDBAccessProvider.getDbAccessor().runDMLAction(new DBAction<DemoEntity>() {
        @Override
        public DemoEntity run(DAOContext daoContext) throws Exception {
            DemoEntity entity=new DemoEntity();
            entity.setId("123123");
            daoContext.getDAO(DemoDao.class).remove("id");// delete by id
            daoContext.getDAO(DemoDao.class).remove(new QueryConditionImpl().addRestriction(RestrictionFactory.eq("id", entity.getId())));// delete by queryCondition
            return null;
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}

Update record:

try {
    DemoDBAccessProvider.getDbAccessor().runDMLAction(new DBAction<DemoEntity>() {
        @Override
        public DemoEntity run(DAOContext daoContext) throws Exception {
            DemoEntity entity=new DemoEntity();
            entity.setId("123123");
            daoContext.getDAO(DemoDao.class).update(entity);// update by id
            daoContext.getDAO(DemoDao.class).addOrUpdate(entity);// add or update
            return null;
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}

results matching ""

    No results matching ""