Folder structure for PandaLib
This commit is contained in:
parent
3c3ba8bca3
commit
4da86314c8
0
.gitignore → Core/.gitignore
vendored
0
.gitignore → Core/.gitignore
vendored
@ -1,391 +1,391 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
import fr.pandacube.util.Log;
|
import fr.pandacube.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>ORM = Object-Relational Mapping</b>
|
* <b>ORM = Object-Relational Mapping</b>
|
||||||
*
|
*
|
||||||
* @author Marc Baloup
|
* @author Marc Baloup
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class ORM {
|
public final class ORM {
|
||||||
|
|
||||||
private static List<Class<? extends SQLElement<?>>> tables = new ArrayList<>();
|
private static List<Class<? extends SQLElement<?>>> tables = new ArrayList<>();
|
||||||
private static Map<Class<? extends SQLElement<?>>, String> tableNames = new HashMap<>();
|
private static Map<Class<? extends SQLElement<?>>, String> tableNames = new HashMap<>();
|
||||||
|
|
||||||
private static DBConnection connection;
|
private static DBConnection connection;
|
||||||
|
|
||||||
public static DBConnection getConnection() {
|
public static DBConnection getConnection() {
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static <E extends SQLElement<E>> void init(DBConnection conn) {
|
public synchronized static <E extends SQLElement<E>> void init(DBConnection conn) {
|
||||||
|
|
||||||
connection = conn;
|
connection = conn;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized <E extends SQLElement<E>> void initTable(Class<E> elemClass) throws ORMInitTableException {
|
public static synchronized <E extends SQLElement<E>> void initTable(Class<E> elemClass) throws ORMInitTableException {
|
||||||
if (tables.contains(elemClass)) return;
|
if (tables.contains(elemClass)) return;
|
||||||
try {
|
try {
|
||||||
tables.add(elemClass);
|
tables.add(elemClass);
|
||||||
Log.debug("[ORM] Start Init SQL table "+elemClass.getSimpleName());
|
Log.debug("[ORM] Start Init SQL table "+elemClass.getSimpleName());
|
||||||
E instance = elemClass.getConstructor().newInstance();
|
E instance = elemClass.getConstructor().newInstance();
|
||||||
String tableName = instance.tableName();
|
String tableName = instance.tableName();
|
||||||
tableNames.put(elemClass, tableName);
|
tableNames.put(elemClass, tableName);
|
||||||
if (!tableExistInDB(tableName)) createTable(instance);
|
if (!tableExistInDB(tableName)) createTable(instance);
|
||||||
Log.debug("[ORM] End init SQL table "+elemClass.getSimpleName());
|
Log.debug("[ORM] End init SQL table "+elemClass.getSimpleName());
|
||||||
} catch (Exception|ExceptionInInitializerError e) {
|
} catch (Exception|ExceptionInInitializerError e) {
|
||||||
throw new ORMInitTableException(elemClass, e);
|
throw new ORMInitTableException(elemClass, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <E extends SQLElement<E>> void createTable(E elem) throws SQLException {
|
private static <E extends SQLElement<E>> void createTable(E elem) throws SQLException {
|
||||||
|
|
||||||
String sql = "CREATE TABLE IF NOT EXISTS " + elem.tableName() + " (";
|
String sql = "CREATE TABLE IF NOT EXISTS " + elem.tableName() + " (";
|
||||||
List<Object> params = new ArrayList<>();
|
List<Object> params = new ArrayList<>();
|
||||||
|
|
||||||
Collection<SQLField<E, ?>> tableFields = elem.getFields().values();
|
Collection<SQLField<E, ?>> tableFields = elem.getFields().values();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (SQLField<E, ?> f : tableFields) {
|
for (SQLField<E, ?> f : tableFields) {
|
||||||
Pair<String, List<Object>> statementPart = f.forSQLPreparedStatement();
|
Pair<String, List<Object>> statementPart = f.forSQLPreparedStatement();
|
||||||
params.addAll(statementPart.getValue1());
|
params.addAll(statementPart.getValue1());
|
||||||
|
|
||||||
if (!first) sql += ", ";
|
if (!first) sql += ", ";
|
||||||
first = false;
|
first = false;
|
||||||
sql += statementPart.getValue0();
|
sql += statementPart.getValue0();
|
||||||
}
|
}
|
||||||
|
|
||||||
sql += ", PRIMARY KEY id(id))";
|
sql += ", PRIMARY KEY id(id))";
|
||||||
|
|
||||||
try (PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql)) {
|
try (PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql)) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (Object val : params)
|
for (Object val : params)
|
||||||
ps.setObject(i++, val);
|
ps.setObject(i++, val);
|
||||||
Log.info("Creating table " + elem.tableName() + ":\n" + ps.toString());
|
Log.info("Creating table " + elem.tableName() + ":\n" + ps.toString());
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> String getTableName(Class<E> elemClass) throws ORMException {
|
public static <E extends SQLElement<E>> String getTableName(Class<E> elemClass) throws ORMException {
|
||||||
initTable(elemClass);
|
initTable(elemClass);
|
||||||
return tableNames.get(elemClass);
|
return tableNames.get(elemClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean tableExistInDB(String tableName) throws SQLException {
|
private static boolean tableExistInDB(String tableName) throws SQLException {
|
||||||
boolean exist = false;
|
boolean exist = false;
|
||||||
try (ResultSet set = connection.getNativeConnection().getMetaData().getTables(null, null, tableName, null)) {
|
try (ResultSet set = connection.getNativeConnection().getMetaData().getTables(null, null, tableName, null)) {
|
||||||
exist = set.next();
|
exist = set.next();
|
||||||
}
|
}
|
||||||
return exist;
|
return exist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <E extends SQLElement<E>> SQLField<E, Integer> getSQLIdField(Class<E> elemClass)
|
public static <E extends SQLElement<E>> SQLField<E, Integer> getSQLIdField(Class<E> elemClass)
|
||||||
throws ORMInitTableException {
|
throws ORMInitTableException {
|
||||||
initTable(elemClass);
|
initTable(elemClass);
|
||||||
return (SQLField<E, Integer>) SQLElement.fieldsCache.get(elemClass).get("id");
|
return (SQLField<E, Integer>) SQLElement.fieldsCache.get(elemClass).get("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getByIds(Class<E> elemClass, Integer... ids) throws ORMException {
|
public static <E extends SQLElement<E>> SQLElementList<E> getByIds(Class<E> elemClass, Integer... ids) throws ORMException {
|
||||||
return getByIds(elemClass, Arrays.asList(ids));
|
return getByIds(elemClass, Arrays.asList(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getByIds(Class<E> elemClass, Collection<Integer> ids)
|
public static <E extends SQLElement<E>> SQLElementList<E> getByIds(Class<E> elemClass, Collection<Integer> ids)
|
||||||
throws ORMException {
|
throws ORMException {
|
||||||
return getAll(elemClass, getSQLIdField(elemClass).in(ids), SQLOrderBy.asc(getSQLIdField(elemClass)), 1, null);
|
return getAll(elemClass, getSQLIdField(elemClass).in(ids), SQLOrderBy.asc(getSQLIdField(elemClass)), 1, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> E getById(Class<E> elemClass, int id) throws ORMException {
|
public static <E extends SQLElement<E>> E getById(Class<E> elemClass, int id) throws ORMException {
|
||||||
return getFirst(elemClass, getSQLIdField(elemClass).eq(id));
|
return getFirst(elemClass, getSQLIdField(elemClass).eq(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where)
|
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where)
|
||||||
throws ORMException {
|
throws ORMException {
|
||||||
return getFirst(elemClass, where, null, null);
|
return getFirst(elemClass, where, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLOrderBy<E> orderBy)
|
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLOrderBy<E> orderBy)
|
||||||
throws ORMException {
|
throws ORMException {
|
||||||
return getFirst(elemClass, null, orderBy, null);
|
return getFirst(elemClass, null, orderBy, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy)
|
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy)
|
||||||
throws ORMException {
|
throws ORMException {
|
||||||
return getFirst(elemClass, where, orderBy, null);
|
return getFirst(elemClass, where, orderBy, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer offset)
|
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer offset)
|
||||||
throws ORMException {
|
throws ORMException {
|
||||||
SQLElementList<E> elts = getAll(elemClass, where, orderBy, 1, offset);
|
SQLElementList<E> elts = getAll(elemClass, where, orderBy, 1, offset);
|
||||||
return (elts.size() == 0) ? null : elts.get(0);
|
return (elts.size() == 0) ? null : elts.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass) throws ORMException {
|
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass) throws ORMException {
|
||||||
return getAll(elemClass, null, null, null, null);
|
return getAll(elemClass, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
||||||
return getAll(elemClass, where, null, null, null);
|
return getAll(elemClass, where, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy) throws ORMException {
|
SQLOrderBy<E> orderBy) throws ORMException {
|
||||||
return getAll(elemClass, where, orderBy, null, null);
|
return getAll(elemClass, where, orderBy, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy, Integer limit) throws ORMException {
|
SQLOrderBy<E> orderBy, Integer limit) throws ORMException {
|
||||||
return getAll(elemClass, where, orderBy, limit, null);
|
return getAll(elemClass, where, orderBy, limit, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy, Integer limit, Integer offset) throws ORMException {
|
SQLOrderBy<E> orderBy, Integer limit, Integer offset) throws ORMException {
|
||||||
SQLElementList<E> elmts = new SQLElementList<>();
|
SQLElementList<E> elmts = new SQLElementList<>();
|
||||||
forEach(elemClass, where, orderBy, limit, offset, elmts::add);
|
forEach(elemClass, where, orderBy, limit, offset, elmts::add);
|
||||||
return elmts;
|
return elmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, Consumer<E> action) throws ORMException {
|
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, Consumer<E> action) throws ORMException {
|
||||||
forEach(elemClass, null, null, null, null, action);
|
forEach(elemClass, null, null, null, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
||||||
Consumer<E> action) throws ORMException {
|
Consumer<E> action) throws ORMException {
|
||||||
forEach(elemClass, where, null, null, null, action);
|
forEach(elemClass, where, null, null, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy, Consumer<E> action) throws ORMException {
|
SQLOrderBy<E> orderBy, Consumer<E> action) throws ORMException {
|
||||||
forEach(elemClass, where, orderBy, null, null, action);
|
forEach(elemClass, where, orderBy, null, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy, Integer limit, Consumer<E> action) throws ORMException {
|
SQLOrderBy<E> orderBy, Integer limit, Consumer<E> action) throws ORMException {
|
||||||
forEach(elemClass, where, orderBy, limit, null, action);
|
forEach(elemClass, where, orderBy, limit, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
public static <E extends SQLElement<E>> void forEach(Class<E> elemClass, SQLWhere<E> where,
|
||||||
SQLOrderBy<E> orderBy, Integer limit, Integer offset, Consumer<E> action) throws ORMException {
|
SQLOrderBy<E> orderBy, Integer limit, Integer offset, Consumer<E> action) throws ORMException {
|
||||||
initTable(elemClass);
|
initTable(elemClass);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT * FROM " + getTableName(elemClass);
|
String sql = "SELECT * FROM " + getTableName(elemClass);
|
||||||
|
|
||||||
List<Object> params = new ArrayList<>();
|
List<Object> params = new ArrayList<>();
|
||||||
|
|
||||||
if (where != null) {
|
if (where != null) {
|
||||||
Pair<String, List<Object>> ret = where.toSQL();
|
Pair<String, List<Object>> ret = where.toSQL();
|
||||||
sql += " WHERE " + ret.getValue0();
|
sql += " WHERE " + ret.getValue0();
|
||||||
params.addAll(ret.getValue1());
|
params.addAll(ret.getValue1());
|
||||||
}
|
}
|
||||||
if (orderBy != null) sql += " ORDER BY " + orderBy.toSQL();
|
if (orderBy != null) sql += " ORDER BY " + orderBy.toSQL();
|
||||||
if (limit != null) sql += " LIMIT " + limit;
|
if (limit != null) sql += " LIMIT " + limit;
|
||||||
if (offset != null) sql += " OFFSET " + offset;
|
if (offset != null) sql += " OFFSET " + offset;
|
||||||
sql += ";";
|
sql += ";";
|
||||||
|
|
||||||
try (ResultSet set = customQueryStatement(sql, params)) {
|
try (ResultSet set = customQueryStatement(sql, params)) {
|
||||||
while (set.next()) {
|
while (set.next()) {
|
||||||
E elm = getElementInstance(set, elemClass);
|
E elm = getElementInstance(set, elemClass);
|
||||||
action.accept(elm);
|
action.accept(elm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new ORMException(e);
|
throw new ORMException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> long count(Class<E> elemClass) throws ORMException {
|
public static <E extends SQLElement<E>> long count(Class<E> elemClass) throws ORMException {
|
||||||
return count(elemClass, null);
|
return count(elemClass, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> long count(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
public static <E extends SQLElement<E>> long count(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
||||||
initTable(elemClass);
|
initTable(elemClass);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(*) as count FROM " + getTableName(elemClass);
|
String sql = "SELECT COUNT(*) as count FROM " + getTableName(elemClass);
|
||||||
|
|
||||||
List<Object> params = new ArrayList<>();
|
List<Object> params = new ArrayList<>();
|
||||||
|
|
||||||
if (where != null) {
|
if (where != null) {
|
||||||
Pair<String, List<Object>> ret = where.toSQL();
|
Pair<String, List<Object>> ret = where.toSQL();
|
||||||
sql += " WHERE " + ret.getValue0();
|
sql += " WHERE " + ret.getValue0();
|
||||||
params.addAll(ret.getValue1());
|
params.addAll(ret.getValue1());
|
||||||
}
|
}
|
||||||
sql += ";";
|
sql += ";";
|
||||||
|
|
||||||
try (ResultSet set = customQueryStatement(sql, params)) {
|
try (ResultSet set = customQueryStatement(sql, params)) {
|
||||||
if (set.next()) {
|
if (set.next()) {
|
||||||
return set.getLong(1);
|
return set.getLong(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new ORMException(e);
|
throw new ORMException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ORMException("Can’t retrieve element count from database (The ResultSet may be empty)");
|
throw new ORMException("Can’t retrieve element count from database (The ResultSet may be empty)");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ResultSet customQueryStatement(String sql, List<Object> params) throws ORMException {
|
public static ResultSet customQueryStatement(String sql, List<Object> params) throws ORMException {
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql);
|
PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql);
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (Object val : params) {
|
for (Object val : params) {
|
||||||
if (val instanceof Enum<?>) val = ((Enum<?>) val).name();
|
if (val instanceof Enum<?>) val = ((Enum<?>) val).name();
|
||||||
ps.setObject(i++, val);
|
ps.setObject(i++, val);
|
||||||
}
|
}
|
||||||
Log.debug(ps.toString());
|
Log.debug(ps.toString());
|
||||||
|
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
|
|
||||||
ps.closeOnCompletion();
|
ps.closeOnCompletion();
|
||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new ORMException(e);
|
throw new ORMException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLUpdate<E> update(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
public static <E extends SQLElement<E>> SQLUpdate<E> update(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
||||||
return new SQLUpdate<>(elemClass, where);
|
return new SQLUpdate<>(elemClass, where);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static <E extends SQLElement<E>> int update(Class<E> elemClass, SQLWhere<E> where, Map<SQLField<E, ?>, Object> values) throws ORMException {
|
/* package */ static <E extends SQLElement<E>> int update(Class<E> elemClass, SQLWhere<E> where, Map<SQLField<E, ?>, Object> values) throws ORMException {
|
||||||
return new SQLUpdate<>(elemClass, where, values).execute();
|
return new SQLUpdate<>(elemClass, where, values).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the elements of the table represented by {@code elemClass} which meet the condition {@code where}.
|
* Delete the elements of the table represented by {@code elemClass} which meet the condition {@code where}.
|
||||||
* @param elemClass the SQLElement representing the table.
|
* @param elemClass the SQLElement representing the table.
|
||||||
* @param where the condition to meet for an element to be deleted from the table. If null, the table is truncated using {@link #truncateTable(Class)}.
|
* @param where the condition to meet for an element to be deleted from the table. If null, the table is truncated using {@link #truncateTable(Class)}.
|
||||||
* @return The return value of {@link PreparedStatement#executeUpdate()}, for an SQL query {@code DELETE}.
|
* @return The return value of {@link PreparedStatement#executeUpdate()}, for an SQL query {@code DELETE}.
|
||||||
* @throws ORMException
|
* @throws ORMException
|
||||||
*/
|
*/
|
||||||
public static <E extends SQLElement<E>> int delete(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
public static <E extends SQLElement<E>> int delete(Class<E> elemClass, SQLWhere<E> where) throws ORMException {
|
||||||
initTable(elemClass);
|
initTable(elemClass);
|
||||||
|
|
||||||
if (where == null) {
|
if (where == null) {
|
||||||
return truncateTable(elemClass);
|
return truncateTable(elemClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<String, List<Object>> whereData = where.toSQL();
|
Pair<String, List<Object>> whereData = where.toSQL();
|
||||||
|
|
||||||
String sql = "DELETE FROM " + getTableName(elemClass)
|
String sql = "DELETE FROM " + getTableName(elemClass)
|
||||||
+ " WHERE " + whereData.getValue0()
|
+ " WHERE " + whereData.getValue0()
|
||||||
+ ";";
|
+ ";";
|
||||||
List<Object> params = new ArrayList<>(whereData.getValue1());
|
List<Object> params = new ArrayList<>(whereData.getValue1());
|
||||||
|
|
||||||
return customUpdateStatement(sql, params);
|
return customUpdateStatement(sql, params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static int customUpdateStatement(String sql, List<Object> params) throws ORMException {
|
public static int customUpdateStatement(String sql, List<Object> params) throws ORMException {
|
||||||
try (PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql)) {
|
try (PreparedStatement ps = connection.getNativeConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (Object val : params) {
|
for (Object val : params) {
|
||||||
if (val instanceof Enum<?>) val = ((Enum<?>) val).name();
|
if (val instanceof Enum<?>) val = ((Enum<?>) val).name();
|
||||||
ps.setObject(i++, val);
|
ps.setObject(i++, val);
|
||||||
}
|
}
|
||||||
Log.debug(ps.toString());
|
Log.debug(ps.toString());
|
||||||
|
|
||||||
return ps.executeUpdate();
|
return ps.executeUpdate();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new ORMException(e);
|
throw new ORMException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> int truncateTable(Class<E> elemClass) throws ORMException {
|
public static <E extends SQLElement<E>> int truncateTable(Class<E> elemClass) throws ORMException {
|
||||||
try (Statement stmt = connection.getNativeConnection().createStatement()) {
|
try (Statement stmt = connection.getNativeConnection().createStatement()) {
|
||||||
return stmt.executeUpdate("TRUNCATE `" + getTableName(elemClass) + "`");
|
return stmt.executeUpdate("TRUNCATE `" + getTableName(elemClass) + "`");
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
throw new ORMException(e);
|
throw new ORMException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <E extends SQLElement<E>> E getElementInstance(ResultSet set, Class<E> elemClass) throws ORMException {
|
private static <E extends SQLElement<E>> E getElementInstance(ResultSet set, Class<E> elemClass) throws ORMException {
|
||||||
try {
|
try {
|
||||||
E instance = elemClass.getConstructor(int.class).newInstance(set.getInt("id"));
|
E instance = elemClass.getConstructor(int.class).newInstance(set.getInt("id"));
|
||||||
|
|
||||||
int fieldCount = set.getMetaData().getColumnCount();
|
int fieldCount = set.getMetaData().getColumnCount();
|
||||||
|
|
||||||
for (int c = 1; c <= fieldCount; c++) {
|
for (int c = 1; c <= fieldCount; c++) {
|
||||||
String fieldName = set.getMetaData().getColumnLabel(c);
|
String fieldName = set.getMetaData().getColumnLabel(c);
|
||||||
|
|
||||||
// ignore when field is present in database but not handled by SQLElement instance
|
// ignore when field is present in database but not handled by SQLElement instance
|
||||||
if (!instance.getFields().containsKey(fieldName)) continue;
|
if (!instance.getFields().containsKey(fieldName)) continue;
|
||||||
|
|
||||||
SQLField<E, Object> sqlField = (SQLField<E, Object>) instance.getFields().get(fieldName);
|
SQLField<E, Object> sqlField = (SQLField<E, Object>) instance.getFields().get(fieldName);
|
||||||
|
|
||||||
boolean customType = sqlField.type instanceof SQLCustomType;
|
boolean customType = sqlField.type instanceof SQLCustomType;
|
||||||
|
|
||||||
Object val = set.getObject(c,
|
Object val = set.getObject(c,
|
||||||
(Class<?>)(customType ? ((SQLCustomType<?, ?>)sqlField.type).intermediateJavaType
|
(Class<?>)(customType ? ((SQLCustomType<?, ?>)sqlField.type).intermediateJavaType
|
||||||
: sqlField.type.getJavaType()));
|
: sqlField.type.getJavaType()));
|
||||||
|
|
||||||
if (val == null || set.wasNull()) {
|
if (val == null || set.wasNull()) {
|
||||||
instance.set(sqlField, null, false);
|
instance.set(sqlField, null, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (customType) {
|
if (customType) {
|
||||||
try {
|
try {
|
||||||
val = ((SQLCustomType<Object, Object>)sqlField.type).dbToJavaConv.apply(val);
|
val = ((SQLCustomType<Object, Object>)sqlField.type).dbToJavaConv.apply(val);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ORMException("Error while converting value of field '"+sqlField.getName()+"' with SQLCustomType from "+((SQLCustomType<Object, Object>)sqlField.type).intermediateJavaType
|
throw new ORMException("Error while converting value of field '"+sqlField.getName()+"' with SQLCustomType from "+((SQLCustomType<Object, Object>)sqlField.type).intermediateJavaType
|
||||||
+"(jdbc source) to "+sqlField.type.getJavaType()+"(java destination). The original value is '"+val.toString()+"'", e);
|
+"(jdbc source) to "+sqlField.type.getJavaType()+"(java destination). The original value is '"+val.toString()+"'", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.set(sqlField, val, false);
|
instance.set(sqlField, val, false);
|
||||||
// la valeur venant de la BDD est marqué comme "non modifié"
|
// la valeur venant de la BDD est marqué comme "non modifié"
|
||||||
// dans l'instance car le constructeur de l'instance met
|
// dans l'instance car le constructeur de l'instance met
|
||||||
// tout les champs comme modifiés
|
// tout les champs comme modifiés
|
||||||
instance.modifiedSinceLastSave.remove(sqlField.getName());
|
instance.modifiedSinceLastSave.remove(sqlField.getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance.isValidForSave()) throw new ORMException(
|
if (!instance.isValidForSave()) throw new ORMException(
|
||||||
"This SQLElement representing a database entry is not valid for save : " + instance.toString());
|
"This SQLElement representing a database entry is not valid for save : " + instance.toString());
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | SQLException e) {
|
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | SQLException e) {
|
||||||
throw new ORMException("Can't instanciate " + elemClass.getName(), e);
|
throw new ORMException("Can't instanciate " + elemClass.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ORM() {} // rend la classe non instanciable
|
private ORM() {} // rend la classe non instanciable
|
||||||
|
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,201 +1,201 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
|
||||||
import fr.pandacube.util.Log;
|
import fr.pandacube.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param <E>
|
* @param <E>
|
||||||
*/
|
*/
|
||||||
public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
|
public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final Map<SQLField<E, ?>, Object> modifiedValues = new LinkedHashMap<>();
|
private final Map<SQLField<E, ?>, Object> modifiedValues = new LinkedHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean add(E e) {
|
public synchronized boolean add(E e) {
|
||||||
if (e == null || !e.isStored()) return false;
|
if (e == null || !e.isStored()) return false;
|
||||||
return super.add(e);
|
return super.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Défini une valeur à un champ qui sera appliquée dans la base de données à
|
* Défini une valeur à un champ qui sera appliquée dans la base de données à
|
||||||
* tous les
|
* tous les
|
||||||
* entrées présente dans cette liste lors de l'appel à {@link #saveCommon()}
|
* entrées présente dans cette liste lors de l'appel à {@link #saveCommon()}
|
||||||
* .
|
* .
|
||||||
* Les valeurs stockés dans chaque élément de cette liste ne seront affectés
|
* Les valeurs stockés dans chaque élément de cette liste ne seront affectés
|
||||||
* que lors de
|
* que lors de
|
||||||
* l'appel à {@link #saveCommon()}
|
* l'appel à {@link #saveCommon()}
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* @param field le champs à modifier
|
* @param field le champs à modifier
|
||||||
* @param value la valeur à lui appliquer
|
* @param value la valeur à lui appliquer
|
||||||
*/
|
*/
|
||||||
public synchronized <T> void setCommon(SQLField<E, T> field, T value) {
|
public synchronized <T> void setCommon(SQLField<E, T> field, T value) {
|
||||||
if (field == null)
|
if (field == null)
|
||||||
throw new IllegalArgumentException("field can't be null");
|
throw new IllegalArgumentException("field can't be null");
|
||||||
if (field.getName() == "id")
|
if (field.getName() == "id")
|
||||||
throw new IllegalArgumentException("Can't modify id field in a SQLElementList");
|
throw new IllegalArgumentException("Can't modify id field in a SQLElementList");
|
||||||
|
|
||||||
Class<E> elemClass = field.getSQLElementType();
|
Class<E> elemClass = field.getSQLElementType();
|
||||||
try {
|
try {
|
||||||
E emptyElement = elemClass.getConstructor().newInstance();
|
E emptyElement = elemClass.getConstructor().newInstance();
|
||||||
emptyElement.set(field, value, false);
|
emptyElement.set(field, value, false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("Illegal field or value or can't instanciante an empty instance of "
|
throw new IllegalArgumentException("Illegal field or value or can't instanciante an empty instance of "
|
||||||
+ elemClass.getName() + ". (the instance is only created to test validity of field and value)", e);
|
+ elemClass.getName() + ". (the instance is only created to test validity of field and value)", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ici, la valeur est bonne
|
// ici, la valeur est bonne
|
||||||
modifiedValues.put(field, value);
|
modifiedValues.put(field, value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applique toutes les valeurs défini avec
|
* Applique toutes les valeurs défini avec
|
||||||
* {@link #setCommon(SQLField, Object)} à toutes
|
* {@link #setCommon(SQLField, Object)} à toutes
|
||||||
* les entrées dans la base de données correspondants aux entrées de cette
|
* les entrées dans la base de données correspondants aux entrées de cette
|
||||||
* liste. Les nouvelles
|
* liste. Les nouvelles
|
||||||
* valeurs sont aussi mises à jour dans les objets contenus dans cette
|
* valeurs sont aussi mises à jour dans les objets contenus dans cette
|
||||||
* liste, si la valeur n'a pas été modifiée individuellement avec
|
* liste, si la valeur n'a pas été modifiée individuellement avec
|
||||||
* {@link SQLElement#set(SQLField, Object)}.<br/>
|
* {@link SQLElement#set(SQLField, Object)}.<br/>
|
||||||
* Les objets de cette liste qui n'ont pas leur données en base de données
|
* Les objets de cette liste qui n'ont pas leur données en base de données
|
||||||
* sont ignorées.
|
* sont ignorées.
|
||||||
*
|
*
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public synchronized int saveCommon() throws ORMException {
|
public synchronized int saveCommon() throws ORMException {
|
||||||
List<E> storedEl = getStoredEl();
|
List<E> storedEl = getStoredEl();
|
||||||
if (storedEl.isEmpty()) return 0;
|
if (storedEl.isEmpty()) return 0;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<E> classEl = (Class<E>)storedEl.get(0).getClass();
|
Class<E> classEl = (Class<E>)storedEl.get(0).getClass();
|
||||||
|
|
||||||
int ret = ORM.update(classEl,
|
int ret = ORM.update(classEl,
|
||||||
storedEl.get(0).getFieldId().in(storedEl.stream().map(SQLElement::getId).collect(Collectors.toList())
|
storedEl.get(0).getFieldId().in(storedEl.stream().map(SQLElement::getId).collect(Collectors.toList())
|
||||||
),
|
),
|
||||||
modifiedValues);
|
modifiedValues);
|
||||||
|
|
||||||
applyNewValuesToElements(storedEl);
|
applyNewValuesToElements(storedEl);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void applyNewValuesToElements(List<E> storedEl) {
|
private void applyNewValuesToElements(List<E> storedEl) {
|
||||||
// applique les valeurs dans chaques objets de la liste
|
// applique les valeurs dans chaques objets de la liste
|
||||||
for (E el : storedEl)
|
for (E el : storedEl)
|
||||||
for (@SuppressWarnings("rawtypes")
|
for (@SuppressWarnings("rawtypes")
|
||||||
SQLField entry : modifiedValues.keySet())
|
SQLField entry : modifiedValues.keySet())
|
||||||
if (!el.isModified(entry)) el.set(entry, modifiedValues.get(entry), false);
|
if (!el.isModified(entry)) el.set(entry, modifiedValues.get(entry), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<E> getStoredEl() {
|
private List<E> getStoredEl() {
|
||||||
return stream().filter(SQLElement::isStored).collect(Collectors.toCollection(() -> new ArrayList<>()));
|
return stream().filter(SQLElement::isStored).collect(Collectors.toCollection(() -> new ArrayList<>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated please use {@link ORM#delete(Class, SQLWhere)} instead,
|
* @deprecated please use {@link ORM#delete(Class, SQLWhere)} instead,
|
||||||
* except if you really want to fetch the data before removing them from database.
|
* except if you really want to fetch the data before removing them from database.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public synchronized void removeFromDB() {
|
public synchronized void removeFromDB() {
|
||||||
List<E> storedEl = getStoredEl();
|
List<E> storedEl = getStoredEl();
|
||||||
if (storedEl.isEmpty()) return;
|
if (storedEl.isEmpty()) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<E> classEl = (Class<E>)storedEl.get(0).getClass();
|
Class<E> classEl = (Class<E>)storedEl.get(0).getClass();
|
||||||
|
|
||||||
ORM.delete(classEl,
|
ORM.delete(classEl,
|
||||||
storedEl.get(0).getFieldId().in(storedEl.stream().map(SQLElement::getId).collect(Collectors.toList()))
|
storedEl.get(0).getFieldId().in(storedEl.stream().map(SQLElement::getId).collect(Collectors.toList()))
|
||||||
);
|
);
|
||||||
for (E el : storedEl)
|
for (E el : storedEl)
|
||||||
el.markAsNotStored();
|
el.markAsNotStored();
|
||||||
} catch (ORMException e) {
|
} catch (ORMException e) {
|
||||||
Log.severe(e);
|
Log.severe(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public <T, P extends SQLElement<P>> SQLElementList<P> getReferencedEntries(SQLFKField<E, T, P> foreignKey, SQLOrderBy<P> orderBy) throws ORMException {
|
public <T, P extends SQLElement<P>> SQLElementList<P> getReferencedEntries(SQLFKField<E, T, P> foreignKey, SQLOrderBy<P> orderBy) throws ORMException {
|
||||||
Set<T> values = new HashSet<>();
|
Set<T> values = new HashSet<>();
|
||||||
forEach(v -> {
|
forEach(v -> {
|
||||||
T val = v.get(foreignKey);
|
T val = v.get(foreignKey);
|
||||||
if (val != null)
|
if (val != null)
|
||||||
values.add(val);
|
values.add(val);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
return new SQLElementList<>();
|
return new SQLElementList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ORM.getAll(foreignKey.getForeignElementClass(), foreignKey.getPrimaryField().in(values), orderBy, null, null);
|
return ORM.getAll(foreignKey.getForeignElementClass(), foreignKey.getPrimaryField().in(values), orderBy, null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <T, P extends SQLElement<P>> Map<T, P> getReferencedEntriesInGroups(SQLFKField<E, T, P> foreignKey) throws ORMException {
|
public <T, P extends SQLElement<P>> Map<T, P> getReferencedEntriesInGroups(SQLFKField<E, T, P> foreignKey) throws ORMException {
|
||||||
SQLElementList<P> foreignElemts = getReferencedEntries(foreignKey, null);
|
SQLElementList<P> foreignElemts = getReferencedEntries(foreignKey, null);
|
||||||
|
|
||||||
Map<T, P> ret = new HashMap<>();
|
Map<T, P> ret = new HashMap<>();
|
||||||
foreignElemts.forEach(foreignVal -> ret.put(foreignVal.get(foreignKey.getPrimaryField()), foreignVal));
|
foreignElemts.forEach(foreignVal -> ret.put(foreignVal.get(foreignKey.getPrimaryField()), foreignVal));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public <T, F extends SQLElement<F>> SQLElementList<F> getReferencingForeignEntries(SQLFKField<F, T, E> foreignKey, SQLOrderBy<F> orderBy, Integer limit, Integer offset) throws ORMException {
|
public <T, F extends SQLElement<F>> SQLElementList<F> getReferencingForeignEntries(SQLFKField<F, T, E> foreignKey, SQLOrderBy<F> orderBy, Integer limit, Integer offset) throws ORMException {
|
||||||
Set<T> values = new HashSet<>();
|
Set<T> values = new HashSet<>();
|
||||||
forEach(v -> {
|
forEach(v -> {
|
||||||
T val = v.get(foreignKey.getPrimaryField());
|
T val = v.get(foreignKey.getPrimaryField());
|
||||||
if (val != null)
|
if (val != null)
|
||||||
values.add(val);
|
values.add(val);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
return new SQLElementList<>();
|
return new SQLElementList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ORM.getAll(foreignKey.getSQLElementType(), foreignKey.in(values), orderBy, limit, offset);
|
return ORM.getAll(foreignKey.getSQLElementType(), foreignKey.in(values), orderBy, limit, offset);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <T, F extends SQLElement<F>> Map<T, SQLElementList<F>> getReferencingForeignEntriesInGroups(SQLFKField<F, T, E> foreignKey, SQLOrderBy<F> orderBy, Integer limit, Integer offset) throws ORMException {
|
public <T, F extends SQLElement<F>> Map<T, SQLElementList<F>> getReferencingForeignEntriesInGroups(SQLFKField<F, T, E> foreignKey, SQLOrderBy<F> orderBy, Integer limit, Integer offset) throws ORMException {
|
||||||
SQLElementList<F> foreignElements = getReferencingForeignEntries(foreignKey, orderBy, limit, offset);
|
SQLElementList<F> foreignElements = getReferencingForeignEntries(foreignKey, orderBy, limit, offset);
|
||||||
|
|
||||||
Map<T, SQLElementList<F>> map = new HashMap<>();
|
Map<T, SQLElementList<F>> map = new HashMap<>();
|
||||||
foreignElements.forEach(foreignVal -> {
|
foreignElements.forEach(foreignVal -> {
|
||||||
SQLElementList<F> subList = map.getOrDefault(foreignVal.get(foreignKey), new SQLElementList<>());
|
SQLElementList<F> subList = map.getOrDefault(foreignVal.get(foreignKey), new SQLElementList<>());
|
||||||
subList.add(foreignVal);
|
subList.add(foreignVal);
|
||||||
map.put(foreignVal.get(foreignKey), subList);
|
map.put(foreignVal.get(foreignKey), subList);
|
||||||
});
|
});
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public JsonArray asJsonArray() {
|
public JsonArray asJsonArray() {
|
||||||
JsonArray json = new JsonArray();
|
JsonArray json = new JsonArray();
|
||||||
forEach(el -> json.add(el.asJsonObject()));
|
forEach(el -> json.add(el.asJsonObject()));
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,69 +1,69 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import fr.pandacube.util.Log;
|
import fr.pandacube.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Marc
|
* @author Marc
|
||||||
*
|
*
|
||||||
* @param <F> the table class of this current foreign key field
|
* @param <F> the table class of this current foreign key field
|
||||||
* @param <T> the Java type of this field
|
* @param <T> the Java type of this field
|
||||||
* @param <P> the table class of the targeted primary key
|
* @param <P> the table class of the targeted primary key
|
||||||
*/
|
*/
|
||||||
public class SQLFKField<F extends SQLElement<F>, T, P extends SQLElement<P>> extends SQLField<F, T> {
|
public class SQLFKField<F extends SQLElement<F>, T, P extends SQLElement<P>> extends SQLField<F, T> {
|
||||||
|
|
||||||
private SQLField<P, T> sqlPrimaryKeyField;
|
private SQLField<P, T> sqlPrimaryKeyField;
|
||||||
private Class<P> sqlForeignKeyElemClass;
|
private Class<P> sqlForeignKeyElemClass;
|
||||||
|
|
||||||
protected SQLFKField(SQLType<T> t, boolean nul, T deflt, Class<P> fkEl, SQLField<P, T> fkF) {
|
protected SQLFKField(SQLType<T> t, boolean nul, T deflt, Class<P> fkEl, SQLField<P, T> fkF) {
|
||||||
super(t, nul, deflt);
|
super(t, nul, deflt);
|
||||||
construct(fkEl, fkF);
|
construct(fkEl, fkF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static <E extends SQLElement<E>, F extends SQLElement<F>> SQLFKField<E, Integer, F> idFK(boolean nul, Class<F> fkEl) {
|
/* package */ static <E extends SQLElement<E>, F extends SQLElement<F>> SQLFKField<E, Integer, F> idFK(boolean nul, Class<F> fkEl) {
|
||||||
return idFK(nul, null, fkEl);
|
return idFK(nul, null, fkEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static <E extends SQLElement<E>, F extends SQLElement<F>> SQLFKField<E, Integer, F> idFK(boolean nul, Integer deflt, Class<F> fkEl) {
|
/* package */ static <E extends SQLElement<E>, F extends SQLElement<F>> SQLFKField<E, Integer, F> idFK(boolean nul, Integer deflt, Class<F> fkEl) {
|
||||||
if (fkEl == null) throw new IllegalArgumentException("foreignKeyElement can't be null");
|
if (fkEl == null) throw new IllegalArgumentException("foreignKeyElement can't be null");
|
||||||
try {
|
try {
|
||||||
SQLField<F, Integer> f = ORM.getSQLIdField(fkEl);
|
SQLField<F, Integer> f = ORM.getSQLIdField(fkEl);
|
||||||
return new SQLFKField<>(f.type, nul, deflt, fkEl, f);
|
return new SQLFKField<>(f.type, nul, deflt, fkEl, f);
|
||||||
} catch (ORMInitTableException e) {
|
} catch (ORMInitTableException e) {
|
||||||
Log.severe("Can't create Foreign key Field targetting id field of '"+fkEl+"'", e);
|
Log.severe("Can't create Foreign key Field targetting id field of '"+fkEl+"'", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static <E extends SQLElement<E>, T, F extends SQLElement<F>> SQLFKField<E, T, F> customFK(boolean nul, Class<F> fkEl, SQLField<F, T> fkF) {
|
/* package */ static <E extends SQLElement<E>, T, F extends SQLElement<F>> SQLFKField<E, T, F> customFK(boolean nul, Class<F> fkEl, SQLField<F, T> fkF) {
|
||||||
return customFK(nul, null, fkEl, fkF);
|
return customFK(nul, null, fkEl, fkF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static <E extends SQLElement<E>, T, F extends SQLElement<F>> SQLFKField<E, T, F> customFK(boolean nul, T deflt, Class<F> fkEl, SQLField<F, T> fkF) {
|
/* package */ static <E extends SQLElement<E>, T, F extends SQLElement<F>> SQLFKField<E, T, F> customFK(boolean nul, T deflt, Class<F> fkEl, SQLField<F, T> fkF) {
|
||||||
if (fkEl == null) throw new IllegalArgumentException("foreignKeyElement can't be null");
|
if (fkEl == null) throw new IllegalArgumentException("foreignKeyElement can't be null");
|
||||||
return new SQLFKField<>(fkF.type, nul, deflt, fkEl, fkF);
|
return new SQLFKField<>(fkF.type, nul, deflt, fkEl, fkF);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void construct(Class<P> fkEl, SQLField<P, T> fkF) {
|
private void construct(Class<P> fkEl, SQLField<P, T> fkF) {
|
||||||
if (fkF == null) throw new IllegalArgumentException("foreignKeyField can't be null");
|
if (fkF == null) throw new IllegalArgumentException("foreignKeyField can't be null");
|
||||||
try {
|
try {
|
||||||
ORM.initTable(fkEl);
|
ORM.initTable(fkEl);
|
||||||
} catch (ORMInitTableException e) {
|
} catch (ORMInitTableException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fkF.getSQLElementType() == null)
|
if (fkF.getSQLElementType() == null)
|
||||||
throw new RuntimeException("Can't initialize foreign key. The primary key in the table " + fkEl.getName() + " is not properly initialized and can't be targetted by a forein key");
|
throw new RuntimeException("Can't initialize foreign key. The primary key in the table " + fkEl.getName() + " is not properly initialized and can't be targetted by a forein key");
|
||||||
sqlPrimaryKeyField = fkF;
|
sqlPrimaryKeyField = fkF;
|
||||||
sqlForeignKeyElemClass = fkEl;
|
sqlForeignKeyElemClass = fkEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLField<P, T> getPrimaryField() {
|
public SQLField<P, T> getPrimaryField() {
|
||||||
return sqlPrimaryKeyField;
|
return sqlPrimaryKeyField;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<P> getForeignElementClass() {
|
public Class<P> getForeignElementClass() {
|
||||||
return sqlForeignKeyElemClass;
|
return sqlForeignKeyElemClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,141 +1,141 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
import fr.pandacube.util.orm.SQLWhereComp.SQLComparator;
|
import fr.pandacube.util.orm.SQLWhereComp.SQLComparator;
|
||||||
|
|
||||||
public class SQLField<E extends SQLElement<E>, T> {
|
public class SQLField<E extends SQLElement<E>, T> {
|
||||||
|
|
||||||
private Class<E> sqlElemClass;
|
private Class<E> sqlElemClass;
|
||||||
private String name = null;
|
private String name = null;
|
||||||
public final SQLType<T> type;
|
public final SQLType<T> type;
|
||||||
public final boolean canBeNull;
|
public final boolean canBeNull;
|
||||||
public final boolean autoIncrement;
|
public final boolean autoIncrement;
|
||||||
/* package */ final T defaultValue;
|
/* package */ final T defaultValue;
|
||||||
|
|
||||||
/* package */ SQLField(SQLType<T> t, boolean nul, boolean autoIncr, T deflt) {
|
/* package */ SQLField(SQLType<T> t, boolean nul, boolean autoIncr, T deflt) {
|
||||||
type = t;
|
type = t;
|
||||||
canBeNull = nul;
|
canBeNull = nul;
|
||||||
autoIncrement = autoIncr;
|
autoIncrement = autoIncr;
|
||||||
defaultValue = deflt;
|
defaultValue = deflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ SQLField(SQLType<T> t, boolean nul) {
|
/* package */ SQLField(SQLType<T> t, boolean nul) {
|
||||||
this(t, nul, false, null);
|
this(t, nul, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ SQLField(SQLType<T> t, boolean nul, boolean autoIncr) {
|
/* package */ SQLField(SQLType<T> t, boolean nul, boolean autoIncr) {
|
||||||
this(t, nul, autoIncr, null);
|
this(t, nul, autoIncr, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ SQLField(SQLType<T> t, boolean nul, T deflt) {
|
/* package */ SQLField(SQLType<T> t, boolean nul, T deflt) {
|
||||||
this(t, nul, false, deflt);
|
this(t, nul, false, deflt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ Pair<String, List<Object>> forSQLPreparedStatement() {
|
/* package */ Pair<String, List<Object>> forSQLPreparedStatement() {
|
||||||
List<Object> params = new ArrayList<>(1);
|
List<Object> params = new ArrayList<>(1);
|
||||||
if (defaultValue != null && !autoIncrement) params.add(defaultValue);
|
if (defaultValue != null && !autoIncrement) params.add(defaultValue);
|
||||||
return new Pair<>("`" + getName() + "` " + type.toString() + (canBeNull ? " NULL" : " NOT NULL")
|
return new Pair<>("`" + getName() + "` " + type.toString() + (canBeNull ? " NULL" : " NOT NULL")
|
||||||
+ (autoIncrement ? " AUTO_INCREMENT" : "")
|
+ (autoIncrement ? " AUTO_INCREMENT" : "")
|
||||||
+ ((defaultValue == null || autoIncrement) ? "" : " DEFAULT ?"), params);
|
+ ((defaultValue == null || autoIncrement) ? "" : " DEFAULT ?"), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void setSQLElementType(Class<E> elemClass) {
|
/* package */ void setSQLElementType(Class<E> elemClass) {
|
||||||
sqlElemClass = elemClass;
|
sqlElemClass = elemClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<E> getSQLElementType() {
|
public Class<E> getSQLElementType() {
|
||||||
return sqlElemClass;
|
return sqlElemClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void setName(String n) {
|
/* package */ void setName(String n) {
|
||||||
name = n;
|
name = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Don't use this {@link #toString()} method in a SQL query, because
|
* <b>Don't use this {@link #toString()} method in a SQL query, because
|
||||||
* the default value is not escaped correctly</b>
|
* the default value is not escaped correctly</b>
|
||||||
*
|
*
|
||||||
* @see java.lang.Object#toString()
|
* @see java.lang.Object#toString()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return forSQLPreparedStatement().getValue0().replaceFirst("\\?",
|
return forSQLPreparedStatement().getValue0().replaceFirst("\\?",
|
||||||
(defaultValue != null && !autoIncrement) ? defaultValue.toString() : "");
|
(defaultValue != null && !autoIncrement) ? defaultValue.toString() : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null) return false;
|
if (obj == null) return false;
|
||||||
if (!(obj instanceof SQLField)) return false;
|
if (!(obj instanceof SQLField)) return false;
|
||||||
SQLField<?, ?> f = (SQLField<?, ?>) obj;
|
SQLField<?, ?> f = (SQLField<?, ?>) obj;
|
||||||
if (!f.getName().equals(getName())) return false;
|
if (!f.getName().equals(getName())) return false;
|
||||||
if (!f.sqlElemClass.equals(sqlElemClass)) return false;
|
if (!f.sqlElemClass.equals(sqlElemClass)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return getName().hashCode() + sqlElemClass.hashCode();
|
return getName().hashCode() + sqlElemClass.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SQLWhere<E> eq(T r) {
|
public SQLWhere<E> eq(T r) {
|
||||||
return comp(SQLComparator.EQ, r);
|
return comp(SQLComparator.EQ, r);
|
||||||
}
|
}
|
||||||
public SQLWhere<E> geq(T r) {
|
public SQLWhere<E> geq(T r) {
|
||||||
return comp(SQLComparator.GEQ, r);
|
return comp(SQLComparator.GEQ, r);
|
||||||
}
|
}
|
||||||
public SQLWhere<E> gt(T r) {
|
public SQLWhere<E> gt(T r) {
|
||||||
return comp(SQLComparator.GT, r);
|
return comp(SQLComparator.GT, r);
|
||||||
}
|
}
|
||||||
public SQLWhere<E> leq(T r) {
|
public SQLWhere<E> leq(T r) {
|
||||||
return comp(SQLComparator.LEQ, r);
|
return comp(SQLComparator.LEQ, r);
|
||||||
}
|
}
|
||||||
public SQLWhere<E> lt(T r) {
|
public SQLWhere<E> lt(T r) {
|
||||||
return comp(SQLComparator.LT, r);
|
return comp(SQLComparator.LT, r);
|
||||||
}
|
}
|
||||||
public SQLWhere<E> neq(T r) {
|
public SQLWhere<E> neq(T r) {
|
||||||
return comp(SQLComparator.NEQ, r);
|
return comp(SQLComparator.NEQ, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SQLWhere<E> comp(SQLComparator c, T r) {
|
private SQLWhere<E> comp(SQLComparator c, T r) {
|
||||||
if (r == null)
|
if (r == null)
|
||||||
throw new IllegalArgumentException("The value cannot be null. Use SQLField#isNull(value) or SQLField#isNotNull(value) to check for null values");
|
throw new IllegalArgumentException("The value cannot be null. Use SQLField#isNull(value) or SQLField#isNotNull(value) to check for null values");
|
||||||
return new SQLWhereComp<>(this, c, r);
|
return new SQLWhereComp<>(this, c, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SQLWhere<E> like(String like) {
|
public SQLWhere<E> like(String like) {
|
||||||
return new SQLWhereLike<>(this, like);
|
return new SQLWhereLike<>(this, like);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SQLWhere<E> in(Collection<T> v) {
|
public SQLWhere<E> in(Collection<T> v) {
|
||||||
return new SQLWhereIn<>(this, v);
|
return new SQLWhereIn<>(this, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SQLWhere<E> isNull() {
|
public SQLWhere<E> isNull() {
|
||||||
return new SQLWhereNull<>(this, true);
|
return new SQLWhereNull<>(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLWhere<E> isNotNull() {
|
public SQLWhere<E> isNotNull() {
|
||||||
return new SQLWhereNull<>(this, false);
|
return new SQLWhereNull<>(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,97 +1,97 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SQLOrderBy<E extends SQLElement<E>> {
|
public class SQLOrderBy<E extends SQLElement<E>> {
|
||||||
|
|
||||||
private List<OBField> orderByFields = new ArrayList<>();
|
private List<OBField> orderByFields = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construit une nouvelle clause ORDER BY
|
* Construit une nouvelle clause ORDER BY
|
||||||
*/
|
*/
|
||||||
private SQLOrderBy() {}
|
private SQLOrderBy() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ajoute un champ dans la clause ORDER BY en construction
|
* Ajoute un champ dans la clause ORDER BY en construction
|
||||||
*
|
*
|
||||||
* @param field le champ SQL à ordonner
|
* @param field le champ SQL à ordonner
|
||||||
* @param d le sens de tri (croissant ASC ou décroissant DESC)
|
* @param d le sens de tri (croissant ASC ou décroissant DESC)
|
||||||
* @return l'objet courant (permet de chainer les ajouts de champs)
|
* @return l'objet courant (permet de chainer les ajouts de champs)
|
||||||
*/
|
*/
|
||||||
private SQLOrderBy<E> add(SQLField<E, ?> field, Direction d) {
|
private SQLOrderBy<E> add(SQLField<E, ?> field, Direction d) {
|
||||||
orderByFields.add(new OBField(field, d));
|
orderByFields.add(new OBField(field, d));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ajoute un champ dans la clause ORDER BY en construction avec pour direction ASC
|
* Ajoute un champ dans la clause ORDER BY en construction avec pour direction ASC
|
||||||
*
|
*
|
||||||
* @param field le champ SQL à ordonner
|
* @param field le champ SQL à ordonner
|
||||||
* @return l'objet courant (permet de chainer les ajouts de champs)
|
* @return l'objet courant (permet de chainer les ajouts de champs)
|
||||||
*/
|
*/
|
||||||
public SQLOrderBy<E> thenAsc(SQLField<E, ?> field) {
|
public SQLOrderBy<E> thenAsc(SQLField<E, ?> field) {
|
||||||
return add(field, Direction.ASC);
|
return add(field, Direction.ASC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ajoute un champ dans la clause ORDER BY en construction avec pour direction DESC
|
* Ajoute un champ dans la clause ORDER BY en construction avec pour direction DESC
|
||||||
*
|
*
|
||||||
* @param field le champ SQL à ordonner
|
* @param field le champ SQL à ordonner
|
||||||
* @return l'objet courant (permet de chainer les ajouts de champs)
|
* @return l'objet courant (permet de chainer les ajouts de champs)
|
||||||
*/
|
*/
|
||||||
public SQLOrderBy<E> thenDesc(SQLField<E, ?> field) {
|
public SQLOrderBy<E> thenDesc(SQLField<E, ?> field) {
|
||||||
return add(field, Direction.DESC);
|
return add(field, Direction.DESC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ String toSQL() {
|
/* package */ String toSQL() {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (OBField f : orderByFields) {
|
for (OBField f : orderByFields) {
|
||||||
if (!first) ret += ", ";
|
if (!first) ret += ", ";
|
||||||
first = false;
|
first = false;
|
||||||
ret += "`" + f.field.getName() + "` " + f.direction.name();
|
ret += "`" + f.field.getName() + "` " + f.direction.name();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toSQL();
|
return toSQL();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OBField {
|
private class OBField {
|
||||||
public final SQLField<E, ?> field;
|
public final SQLField<E, ?> field;
|
||||||
public final Direction direction;
|
public final Direction direction;
|
||||||
|
|
||||||
public OBField(SQLField<E, ?> f, Direction d) {
|
public OBField(SQLField<E, ?> f, Direction d) {
|
||||||
field = f;
|
field = f;
|
||||||
direction = d;
|
direction = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum Direction {
|
private enum Direction {
|
||||||
ASC, DESC;
|
ASC, DESC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLOrderBy<E> asc(SQLField<E, ?> field) {
|
public static <E extends SQLElement<E>> SQLOrderBy<E> asc(SQLField<E, ?> field) {
|
||||||
return new SQLOrderBy<E>().thenAsc(field);
|
return new SQLOrderBy<E>().thenAsc(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLOrderBy<E> desc(SQLField<E, ?> field) {
|
public static <E extends SQLElement<E>> SQLOrderBy<E> desc(SQLField<E, ?> field) {
|
||||||
return new SQLOrderBy<E>().thenDesc(field);
|
return new SQLOrderBy<E>().thenDesc(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,39 +1,39 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
public class SQLType<T> {
|
public class SQLType<T> {
|
||||||
|
|
||||||
protected final String sqlDeclaration;
|
protected final String sqlDeclaration;
|
||||||
private final Class<T> javaTypes;
|
private final Class<T> javaTypes;
|
||||||
|
|
||||||
/* package */ SQLType(String sqlD, Class<T> javaT) {
|
/* package */ SQLType(String sqlD, Class<T> javaT) {
|
||||||
sqlDeclaration = sqlD;
|
sqlDeclaration = sqlD;
|
||||||
javaTypes = javaT;
|
javaTypes = javaT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return sqlDeclaration;
|
return sqlDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssignableFrom(Object val) {
|
public boolean isAssignableFrom(Object val) {
|
||||||
if (javaTypes.isInstance(val)) return true;
|
if (javaTypes.isInstance(val)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return toString().hashCode();
|
return toString().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null || !(obj instanceof SQLType)) return false;
|
if (obj == null || !(obj instanceof SQLType)) return false;
|
||||||
return toString().equals(((SQLType<?>) obj).toString());
|
return toString().equals(((SQLType<?>) obj).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<T> getJavaType() {
|
public Class<T> getJavaType() {
|
||||||
return javaTypes;
|
return javaTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,43 +1,43 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
import fr.pandacube.util.Log;
|
import fr.pandacube.util.Log;
|
||||||
|
|
||||||
public abstract class SQLWhere<E extends SQLElement<E>> {
|
public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||||
|
|
||||||
public abstract Pair<String, List<Object>> toSQL() throws ORMException;
|
public abstract Pair<String, List<Object>> toSQL() throws ORMException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
try {
|
try {
|
||||||
return toSQL().getValue0();
|
return toSQL().getValue0();
|
||||||
} catch (ORMException e) {
|
} catch (ORMException e) {
|
||||||
Log.warning(e);
|
Log.warning(e);
|
||||||
return "[SQLWhere.toString() error (see logs)]";
|
return "[SQLWhere.toString() error (see logs)]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLWhereAnd<E> and(SQLWhere<E> other) {
|
public SQLWhereAnd<E> and(SQLWhere<E> other) {
|
||||||
return new SQLWhereAnd<E>().and(this).and(other);
|
return new SQLWhereAnd<E>().and(this).and(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLWhereOr<E> or(SQLWhere<E> other) {
|
public SQLWhereOr<E> or(SQLWhere<E> other) {
|
||||||
return new SQLWhereOr<E>().or(this).or(other);
|
return new SQLWhereOr<E>().or(this).or(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLWhereAnd<E> and() {
|
public static <E extends SQLElement<E>> SQLWhereAnd<E> and() {
|
||||||
return new SQLWhereAnd<>();
|
return new SQLWhereAnd<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends SQLElement<E>> SQLWhereOr<E> or() {
|
public static <E extends SQLElement<E>> SQLWhereOr<E> or() {
|
||||||
return new SQLWhereOr<>();
|
return new SQLWhereOr<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String escapeLike(String str) {
|
public static String escapeLike(String str) {
|
||||||
return str.replace("\\", "\\\\").replace("_", "\\_").replace("%", "\\%");
|
return str.replace("\\", "\\\\").replace("_", "\\_").replace("%", "\\%");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,58 +1,58 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
public abstract class SQLWhereChain<E extends SQLElement<E>> extends SQLWhere<E> {
|
public abstract class SQLWhereChain<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||||
|
|
||||||
private SQLBoolOp operator;
|
private SQLBoolOp operator;
|
||||||
protected List<SQLWhere<E>> conditions = new ArrayList<>();
|
protected List<SQLWhere<E>> conditions = new ArrayList<>();
|
||||||
|
|
||||||
/* package */ SQLWhereChain(SQLBoolOp op) {
|
/* package */ SQLWhereChain(SQLBoolOp op) {
|
||||||
if (op == null) throw new IllegalArgumentException("op can't be null");
|
if (op == null) throw new IllegalArgumentException("op can't be null");
|
||||||
operator = op;
|
operator = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(SQLWhere<E> sqlWhere) {
|
protected void add(SQLWhere<E> sqlWhere) {
|
||||||
if (sqlWhere == null) throw new IllegalArgumentException("sqlWhere can't be null");
|
if (sqlWhere == null) throw new IllegalArgumentException("sqlWhere can't be null");
|
||||||
conditions.add(sqlWhere);
|
conditions.add(sqlWhere);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<String, List<Object>> toSQL() throws ORMException {
|
public Pair<String, List<Object>> toSQL() throws ORMException {
|
||||||
if (conditions.isEmpty()) {
|
if (conditions.isEmpty()) {
|
||||||
throw new ORMException("SQLWhereChain needs at least one element inside !");
|
throw new ORMException("SQLWhereChain needs at least one element inside !");
|
||||||
}
|
}
|
||||||
|
|
||||||
String sql = "";
|
String sql = "";
|
||||||
List<Object> params = new ArrayList<>();
|
List<Object> params = new ArrayList<>();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
|
||||||
for (SQLWhere<E> w : conditions) {
|
for (SQLWhere<E> w : conditions) {
|
||||||
if (!first) sql += " " + operator.sql + " ";
|
if (!first) sql += " " + operator.sql + " ";
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
Pair<String, List<Object>> ret = w.toSQL();
|
Pair<String, List<Object>> ret = w.toSQL();
|
||||||
sql += "(" + ret.getValue0() + ")";
|
sql += "(" + ret.getValue0() + ")";
|
||||||
params.addAll(ret.getValue1());
|
params.addAll(ret.getValue1());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pair<>(sql, params);
|
return new Pair<>(sql, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ enum SQLBoolOp {
|
/* package */ enum SQLBoolOp {
|
||||||
/** Equivalent to SQL "<code>AND</code>" */
|
/** Equivalent to SQL "<code>AND</code>" */
|
||||||
AND("AND"),
|
AND("AND"),
|
||||||
/** Equivalent to SQL "<code>OR</code>" */
|
/** Equivalent to SQL "<code>OR</code>" */
|
||||||
OR("OR");
|
OR("OR");
|
||||||
/* package */ final String sql;
|
/* package */ final String sql;
|
||||||
|
|
||||||
private SQLBoolOp(String s) {
|
private SQLBoolOp(String s) {
|
||||||
sql = s;
|
sql = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,58 +1,58 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
/* package */ class SQLWhereComp<E extends SQLElement<E>> extends SQLWhere<E> {
|
/* package */ class SQLWhereComp<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||||
|
|
||||||
private SQLField<E, ?> left;
|
private SQLField<E, ?> left;
|
||||||
private SQLComparator comp;
|
private SQLComparator comp;
|
||||||
private Object right;
|
private Object right;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare a field with a value
|
* Compare a field with a value
|
||||||
*
|
*
|
||||||
* @param l the field at left of the comparison operator. Can't be null
|
* @param l the field at left of the comparison operator. Can't be null
|
||||||
* @param c the comparison operator, can't be null
|
* @param c the comparison operator, can't be null
|
||||||
* @param r the value at right of the comparison operator. Can't be null
|
* @param r the value at right of the comparison operator. Can't be null
|
||||||
*/
|
*/
|
||||||
/* package */ <T> SQLWhereComp(SQLField<E, T> l, SQLComparator c, T r) {
|
/* package */ <T> SQLWhereComp(SQLField<E, T> l, SQLComparator c, T r) {
|
||||||
if (l == null || r == null || c == null)
|
if (l == null || r == null || c == null)
|
||||||
throw new IllegalArgumentException("All arguments for SQLWhereComp constructor can't be null");
|
throw new IllegalArgumentException("All arguments for SQLWhereComp constructor can't be null");
|
||||||
left = l;
|
left = l;
|
||||||
comp = c;
|
comp = c;
|
||||||
right = r;
|
right = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<String, List<Object>> toSQL() throws ORMException {
|
public Pair<String, List<Object>> toSQL() throws ORMException {
|
||||||
List<Object> params = new ArrayList<>();
|
List<Object> params = new ArrayList<>();
|
||||||
SQLElement.addValueToSQLObjectList(params, left, right);
|
SQLElement.addValueToSQLObjectList(params, left, right);
|
||||||
return new Pair<>("`" + left.getName() + "` " + comp.sql + " ? ", params);
|
return new Pair<>("`" + left.getName() + "` " + comp.sql + " ? ", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ enum SQLComparator {
|
/* package */ enum SQLComparator {
|
||||||
/** Equivalent to SQL "<code>=</code>" */
|
/** Equivalent to SQL "<code>=</code>" */
|
||||||
EQ("="),
|
EQ("="),
|
||||||
/** Equivalent to SQL "<code>></code>" */
|
/** Equivalent to SQL "<code>></code>" */
|
||||||
GT(">"),
|
GT(">"),
|
||||||
/** Equivalent to SQL "<code>>=</code>" */
|
/** Equivalent to SQL "<code>>=</code>" */
|
||||||
GEQ(">="),
|
GEQ(">="),
|
||||||
/** Equivalent to SQL "<code><</code>" */
|
/** Equivalent to SQL "<code><</code>" */
|
||||||
LT("<"),
|
LT("<"),
|
||||||
/** Equivalent to SQL "<code><=</code>" */
|
/** Equivalent to SQL "<code><=</code>" */
|
||||||
LEQ("<="),
|
LEQ("<="),
|
||||||
/** Equivalent to SQL "<code>!=</code>" */
|
/** Equivalent to SQL "<code>!=</code>" */
|
||||||
NEQ("!=");
|
NEQ("!=");
|
||||||
|
|
||||||
/* package */ final String sql;
|
/* package */ final String sql;
|
||||||
|
|
||||||
private SQLComparator(String s) {
|
private SQLComparator(String s) {
|
||||||
sql = s;
|
sql = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,33 +1,33 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
/* package */ class SQLWhereLike<E extends SQLElement<E>> extends SQLWhere<E> {
|
/* package */ class SQLWhereLike<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||||
|
|
||||||
private SQLField<E, ?> field;
|
private SQLField<E, ?> field;
|
||||||
private String likeExpr;
|
private String likeExpr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare a field with a value
|
* Compare a field with a value
|
||||||
*
|
*
|
||||||
* @param f the field at left of the LIKE keyword. Can't be null
|
* @param f the field at left of the LIKE keyword. Can't be null
|
||||||
* @param like the like expression.
|
* @param like the like expression.
|
||||||
*/
|
*/
|
||||||
/* package */ SQLWhereLike(SQLField<E, ?> f, String like) {
|
/* package */ SQLWhereLike(SQLField<E, ?> f, String like) {
|
||||||
if (f == null || like == null)
|
if (f == null || like == null)
|
||||||
throw new IllegalArgumentException("All arguments for SQLWhereLike constructor can't be null");
|
throw new IllegalArgumentException("All arguments for SQLWhereLike constructor can't be null");
|
||||||
field = f;
|
field = f;
|
||||||
likeExpr = like;
|
likeExpr = like;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<String, List<Object>> toSQL() {
|
public Pair<String, List<Object>> toSQL() {
|
||||||
ArrayList<Object> params = new ArrayList<>();
|
ArrayList<Object> params = new ArrayList<>();
|
||||||
params.add(likeExpr);
|
params.add(likeExpr);
|
||||||
return new Pair<>("`" + field.getName() + "` LIKE ? ", params);
|
return new Pair<>("`" + field.getName() + "` LIKE ? ", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,37 +1,37 @@
|
|||||||
package fr.pandacube.util.orm;
|
package fr.pandacube.util.orm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.javatuples.Pair;
|
import org.javatuples.Pair;
|
||||||
|
|
||||||
import fr.pandacube.util.Log;
|
import fr.pandacube.util.Log;
|
||||||
|
|
||||||
/* package */ class SQLWhereNull<E extends SQLElement<E>> extends SQLWhere<E> {
|
/* package */ class SQLWhereNull<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||||
|
|
||||||
private SQLField<E, ?> fild;
|
private SQLField<E, ?> fild;
|
||||||
private boolean nulll;
|
private boolean nulll;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init a IS NULL / IS NOT NULL expression for a SQL WHERE condition.
|
* Init a IS NULL / IS NOT NULL expression for a SQL WHERE condition.
|
||||||
*
|
*
|
||||||
* @param field the field to check null / not null state
|
* @param field the field to check null / not null state
|
||||||
* @param isNull true if we want to ckeck if "IS NULL", or false to check if
|
* @param isNull true if we want to ckeck if "IS NULL", or false to check if
|
||||||
* "IS NOT NULL"
|
* "IS NOT NULL"
|
||||||
*/
|
*/
|
||||||
/* package */ SQLWhereNull(SQLField<E, ?> field, boolean isNull) {
|
/* package */ SQLWhereNull(SQLField<E, ?> field, boolean isNull) {
|
||||||
if (field == null) throw new IllegalArgumentException("field can't be null");
|
if (field == null) throw new IllegalArgumentException("field can't be null");
|
||||||
if (!field.canBeNull) Log.getLogger().log(Level.WARNING,
|
if (!field.canBeNull) Log.getLogger().log(Level.WARNING,
|
||||||
"Useless : Trying to check IS [NOT] NULL on the field " + field.getSQLElementType().getName() + "#"
|
"Useless : Trying to check IS [NOT] NULL on the field " + field.getSQLElementType().getName() + "#"
|
||||||
+ field.getName() + " which is declared in the ORM as 'can't be null'");
|
+ field.getName() + " which is declared in the ORM as 'can't be null'");
|
||||||
fild = field;
|
fild = field;
|
||||||
nulll = isNull;
|
nulll = isNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<String, List<Object>> toSQL() {
|
public Pair<String, List<Object>> toSQL() {
|
||||||
return new Pair<>("`" + fild.getName() + "` IS " + ((nulll) ? "NULL" : "NOT NULL"), new ArrayList<>());
|
return new Pair<>("`" + fild.getName() + "` IS " + ((nulll) ? "NULL" : "NOT NULL"), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user