reforms / reforms

Reforms is repository for framework that help in development with SQL and ORM technics

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RefOrms

Hello, its RefOrms framework. RefOrms is SQL-oriented JDBC framework, similar to Spring Framework JDBC but having several advantages over it. See RefOrms Manual with html preview.

What the project does:

  • Project helps you map your SQL query to your ORM data.

  • Project contains SQL-92 parser to select, update, insert and delete queries.

Why the project is useful:

  • It’s powerfull instrument which helps you to take all from SQL and map it to ORM.

  • It’s not hibernate, it’s not DDL (like JOOQ) it’s only SQL to ORM.

How users can get started with the project:

<dependency>
    <groupId>com.github.reforms</groupId>
    <artifactId>reforms</artifactId>
    <version>2017.08.17</version>
</dependency>

Short example usaging reforms framework in interface programming style:

// Your IClientDao dao interface
public interface IClientDao {

    @TargetQuery("SELECT id, name, state FROM clients WHERE name = ?")
    public Client findClientByName(String clientName);
}
// Your needs
public class ClientHelper {

    public void doSomeWork(java.sql.Connection connection) throws Exception {
        // ... code before
        IClientDao clientdao = com.reforms.orm.OrmDao.createDao(IClientDao.class, connection);
        Client client = clientdao.findClientByName("Gaius Iulius Caesar");
        // ... code after
    }
}

Concept of Usage as Best Practices:

  • One dependency: reforms.jar for all needs

  • One class com.reforms.orm.OrmDao for most of needs

  • Usaging annotated code as little as possible

  • Simple, but powerfull sintaxes for mapping selecting columns to orm fields

  • Reusable SQL query for difference filters

  • Usaging Interface programming style as technic of coding

Job for You and Job for RefOrms:

N Task Your job RefOrms job Example and Details

1

ORM class

+

-

Clien.java

2

SQL query

+

-

SELECT, INSERT, UPDATE, DELETE queries

3

DAO class or DAO interface

+

-

ClienDao.java

4

Parse SQL query

-

+

Building tree expressions for analysis

5

Setting values to PreparedStatement

-

+

ps.setLong("id", 1L);

6

Reading values from ResultSet

-

+

rs.getLong("id");

7

Map ResultSet to ORM class

-

+

Using tree expressions convert rs to ORM

Strengths and Features:

  • Selectable columns:

    • Filtering selectable columns in SELECT clause before SQL query execute

    • Mapping selectable columns to orm fields inside your SQL query, using framework rules

    • Mapping selectable columns to orm fields inside your SQL query, using your custom rules

    • Mapping selectable columns to map data inside your SQL query, using framework rules

    • Mapping selectable columns to map data inside your SQL query, using your custom rules

  • Managing of schema inside your SQL query

  • Filtering data in WHERE/HAVING clause

    • Static filters - required filters inside your SQL query: if filter values absent exception will occure

    • Dynamic filters - optional filters inside your SQL query: if filter values absent SQL query will be changed and SQL expressions for missing filter values will be cut from SQL query

    • Filters are supporting BEAN way, DIRECT way or MAP way

  • Paging data for some dialect of sql

Sintax rules for mapping selecting columns to orm fields inside your SQL query:

At first, take a look at SQL query below

SELECT client_id, CNAME, state AS client_state FROM clients

Column name map to orm field name use next rules:

  1. Under_score column to camelCase field: client_id → clientId

  2. UPPERCASE column to lowercase field: CNAME → cname

  3. AS clause statement has highest priority then column: state client_state → clientState. Be careful, as clause name converting to field name using under_score to camelCase rule only

Adapting column type to orm field type goes through next phases:

  1. Determination of type to reading value from ResultSet - base on syntax rules in select statement

  2. Converting value of this type to the relevant field type of orm - base on syntax rules in select statement

And

  1. Always base on syntax rules in select statement inside AS clause

  2. Аbsolutely ignoring of column type in your db

  3. Only depends on orm field type

Example? At first, take a look at SQL query below

SELECT client_id, client_id AS id, act_time AS t#logTime FROM clients

and orm class

class Client {
    // ....
    int clientId;
    long id;
    java.util.Date logTime;
    // ....
}
  1. Column expression 'client_id' will reading from ResultSet using clientId field type - int. Java code equivalent: rs.getInt(1);

  2. Column expression 'client_id AS id' will reading from ResultSet using id field type - long. Java code equivalent: rs.getLong(2);

  3. Column expression 'act_time AS t#logTime' will reading from ResultSet using t# directive wich mean 'read as java.sql.Timestamp' and convert read value to java.util.Date, because logTime field declared with this type. Java code equivalent: new java.util.Date(rs.getTimestamp(3).getTime());

All directives see in table below

Directive Java Type

z

boolean

y

byte

x

short

i

int

f

float

w

double

l

long

e

java.lang.Enum (user data concrete type)

s or nothing

java.lang.String (default type for reporting)

n

java.math.BigDecimal

I

java.math.BigInteger

d

java.sql.Date

v

java.sql.Time

t

java.sql.Timestamp

a

java.io.InputStream as AsciiStream

b

java.io.InputStream as BinaryStream

u

User Custome Type, need Registry IReportValueConverter

Expected that directive will rarely be used and mainly for date, stream and user types.

Sintax rules for filters:

At first, take a look at SQL query below

SELECT id, name, state FROM clients WHERE id = ?

Its SQL query in common style for filtering result by id. If we use RefOrms framework terminology we can say that query contains static (required) filter by id. And if we use RefOrms framework we can (although not necessarily) rewrite SQL query like this:

SELECT id, name, state FROM clients WHERE id = :id

It’s like Hibernate or Spring way. What happens, if :id filter value will be absent? Exception occur. And it’s correct. But, if we have filter that can be or not to be?

SELECT id, name, state, act_time FROM clients WHERE act_time >= ? AND act_time <= ?

What then? Then the game enters the dynamic filters. How? Easy.

SELECT id, name, state, act_time FROM clients WHERE act_time >= ::begin_from AND act_time <= ::end_to

Double colon is way to use dynamic filters. What happens, if :begin_from will be absent, but :end_to will present? Like below

SELECT id, name, state, act_time FROM clients WHERE act_time <= ?

If both will absent?

SELECT id, name, state, act_time FROM clients

Yes. SQL query was modifed. And it’s powerfull side of RefOrms framework. You don’t need to construct your sql query using if statement in java code. You only declare dynamic or static filters inside SQL query. RefOrms framework supports all SQL-92 predicates (excluding OVERLAPS and MATCH) with dynamic filters. Few examples

-- 1. IN predicate will be removed if states filter will be absent
SELECT id, name, state FROM clients WHERE state IN (::states)

-- 2. LIKE predicate will be removed if name filter will be absent
SELECT id, name, state FROM clients WHERE name LIKE ::name

-- 3. VALUES block predicate will be narrowed down if some filters will be absent OR removed if all filters will be absent
SELECT id, name, state FROM clients WHERE (id, name) = (::id, ::name)

-- and so on

Full Example of usage

1. Your ORM

 package com.reforms.example;

 public class Client {

    private long id;

    private String name;

    private ClientState state;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public ClientState getState() {
        return state;
    }

    public void setState(ClientState state) {
        this.state = state;
    }
}

2. Your ENUM (part of orm)

package com.reforms.example;

import com.reforms.ann.TargetField;
import com.reforms.ann.TargetMethod;

public enum ClientState {
    NEW(0),
    ACTIVE(1),
    BLOCKED(2);

    @TargetField
    private int state;

    private ClientState(int state) {
        this.state = state;
    }

    public int getState() {
        return state;
    }

    @TargetMethod
    public static ClientState getClientState(int state) {
        for (ClientState clientState : values()) {
            if (clientState.state == state) {
                return clientState;
            }
        }
        throw new IllegalStateException("Unknown client with state " + state);
    }
}

3. Your ORM Handler (if need)

package com.reforms.example;

import com.reforms.orm.dao.bobj.model.OrmHandler;

public class ClientHandler implements OrmHandler<Client> {

    private int index;

    @Override
    public void startHandle() {
        index = 0;
        System.out.println("beging...");
    }

    @Override
    public boolean handleOrm(Client dbClient) {
        index++;
        System.out.println("Load client: " + dbClient);
        return true;
    }

    @Override
    public void endHandle() {
        System.out.println("end... Total: " + index);
    }
}

4. Your DAO

package com.reforms.example;

import com.reforms.orm.OrmDao;
import com.reforms.orm.dao.bobj.model.OrmIterator;

import java.sql.Connection;
import java.util.List;

public class ClientDao {

    // Reform api - dao
    private OrmDao ormDao;

    public ClientDao(Connection connection) {
        ormDao = new OrmDao(connection);
    }

    // Load all active clients
    private static final String SELECT_ACTIVE_CLIENTS_QUERY = "SELECT id, name, state FROM clients WHERE state = ?";

    public List<Client> loadActiveClients() throws Exception {
        return ormDao.selectList(Client.class, SELECT_ACTIVE_CLIENTS_QUERY, ClientState.ACTIVE);
    }

    // Load all clients
    private static final String SELECT_ALL_CLIENTS_QUERY = "SELECT id, name, state FROM clients";

    public OrmIterator<Client> loadClients() throws Exception {
        return ormDao.selectIterator(Client.class, SELECT_ALL_CLIENTS_QUERY);
    }

    public void processClients(ClientHandler clientHandler) throws Exception {
        ormDao.selectAndHandle(Client.class, SELECT_ALL_CLIENTS_QUERY, clientHandler);
    }

    // Find client using id
    private static final String FIND_CLIENT_QUERY = "SELECT id, name, state FROM clients WHERE id = ?";

    public Client findClient(long clientId) throws Exception {
        return ormDao.select(Client.class, FIND_CLIENT_QUERY, clientId);
    }

    // Update client name and state
    private static final String UPDATE_CLIENT_QUERY = "UPDATE clients SET name = ?, state = ? WHERE id = ?";

    public int updateClientNameAndState(long clientId, String clientName, ClientState clientState) throws Exception {
        return ormDao.update(UPDATE_CLIENT_QUERY, clientName, clientState, clientId);
    }

    // Delete client using id
    private static final String DELETE_CLIENT_QUERY = "DELETE FROM clients WHERE id = ?";

    public int deleteClient(long clientId) throws Exception {
        return ormDao.delete(DELETE_CLIENT_QUERY, clientId);
    }

    // Insert new client
    private static final String INSERT_CLIENT_QUERY = "INSERT INTO clients (id, name, state) VALUES(?, ?, ?)";

    public void saveClient(long clientId, String clientName, ClientState clientState) throws Exception {
        ormDao.insert(INSERT_CLIENT_QUERY, clientId, clientName, clientState);
    }

}

Any Examples

1. Mapping selecting column values to orm fields, in case, all orm field names differ from column names

SELECT  cl.id AS cid:clientId,                  -- map column 'cl.id' to 'clientId' orm field
                                                -- client.setClientId(cl.id);
                                                -- cid - as clause name in result SQL query: SELECT cl.id AS cid,...
        cl.name AS clientName,                  -- map column 'cl.name' to 'clientName' orm field
                                                -- client.setClientName(cl.name);
        addr.id AS clientAddress.addressId,     -- map column 'addr.id' to 'addressId' orm field inside of clientAddress orm
                                                -- client.getClientAddress().setAddressId(addr.id);
        addr.city AS clientAddress.refCity,     -- map column 'addr.city' to 'refCity' orm field inside of clientAddress orm
                                                -- client.getClientAddress().setCity(addr.city)
        addr.street AS clientAddress.refStreet, -- map column 'addr.street' to 'refStreet' orm field inside of clientAddress orm
                                                -- client.getClientAddress().setRefstreet(addr.street)
        cl.act_time AS t#logDate                -- map column 'cl.act_time' to 'logDate' orm field
                                                -- client.setLogDate(cl.act_time);
                                                -- t# - direct type of act_time - java.util.Date based on java.sql.Timestamp

            FROM client AS cl,
                 address AS addr

About

Reforms is repository for framework that help in development with SQL and ORM technics


Languages

Language:Java 100.0%