An open API service indexing awesome lists of open source software.

https://github.com/reforms/reforms

Reforms is repository for framework that help in development with SQL and ORM technics
https://github.com/reforms/reforms

jdbc jdbc-framework jdbc-orm jdbc-orm-framework orm-framework sql sql-parser

Last synced: 11 days ago
JSON representation

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

Awesome Lists containing this project

README

          

////
License is free for everything
////
RefOrms
-------
Hello, its RefOrms framework.
RefOrms is SQL-oriented JDBC framework, similar to Spring Framework JDBC but having several advantages over it.
See link:https://htmlpreview.github.io/?https://github.com/reforms/ReformsDoc/blob/master/doc.html[RefOrms Manual] with html preview.

What the project does:
~~~~~~~~~~~~~~~~~~~~~
[square]
* 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:
~~~~~~~~~~~~~~~~~~~~~~~~~
[square]
* 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:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[source,xml]
----

com.github.reforms
reforms
2017.08.17

----

Short example usaging reforms framework in interface programming style:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[source,java]
----
// 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:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[square]
* 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:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[options="header,middle,autowidth"]
|===
| N | Task | Your job | RefOrms job | Example and Details
| 1 | ORM class | + | - | <>
| 2 | SQL query | + | - | _SELECT, INSERT, UPDATE, DELETE queries_
| 3 | DAO class or DAO interface | + | - | <>
| 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:
~~~~~~~~~~~~~~~~~~~~~~~
[square]
* 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
[source,sql]
----
SELECT client_id, CNAME, state AS client_state FROM clients
----
Column name map to orm field name use next rules:
[start]
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: pass:q[state] _client_state_ -> clientState. Be careful, as clause _name_ converting to field name using _under_score_ to _camelCase_ rule *only*
[end]

Adapting column type to orm field type goes through next phases:
[start]
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
[end]

And
[start=3]
3. Always base on syntax rules in select statement inside _AS clause_
4. Аbsolutely ignoring of column type in your db
5. Only depends on orm field type
[end]

Example? At first, take a look at SQL query below
[source,sql]
----
SELECT client_id, client_id AS id, act_time AS t#logTime FROM clients
----
and orm class
[source,java]
----
class Client {
// ....
int clientId;
long id;
java.util.Date logTime;
// ....
}
----
[start]
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());_
[end]

All directives see in table below
[options="header,middle,autowidth"]
|===
| 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
[source,sql]
----
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:
[source,sql]
----
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?
[source,sql]
----
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.
[source,sql]
----
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
[source,sql]
----
SELECT id, name, state, act_time FROM clients WHERE act_time <= ?
----
If both will absent?
[source,sql]
----
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
[source,sql]
----
-- 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
~~~~~~~~~~~~~~~~~~~~~
[[E1]]*1. Your ORM*
[source,java]
----
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)*
[source,java]
----
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)*
[source,java]
----
package com.reforms.example;

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

public class ClientHandler implements OrmHandler {

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);
}
}
----
[[E4]]*4. Your DAO*
[source,java]
----
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 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 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*
[source,sql]
----
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
----