[DEV] continue refacto

This commit is contained in:
Edouard DUPIN 2023-10-15 23:36:01 +02:00
parent d8c6de7bde
commit e64c70cd86
22 changed files with 493 additions and 321 deletions

View File

@ -20,7 +20,6 @@
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes> <attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>

View File

@ -58,7 +58,7 @@ public class AnnotationTools {
} }
return tmp; return tmp;
} }
public static Integer getLimitSize(final Field element) throws Exception { public static Integer getLimitSize(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class);
if (annotation.length == 0) { if (annotation.length == 0) {
@ -69,7 +69,7 @@ public class AnnotationTools {
} }
return ((Column) annotation[0]).length(); return ((Column) annotation[0]).length();
} }
public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) { public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) {
try { try {
final Annotation[] anns = field.getAnnotations(); final Annotation[] anns = field.getAnnotations();
@ -92,22 +92,37 @@ public class AnnotationTools {
} }
return false; return false;
} }
public static boolean getNotNull(final Field element) throws Exception { public static String getFieldName(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class);
if (annotation.length == 0) { if (annotation.length == 0) {
return true; return element.getName();
} }
if (annotation.length > 1) { if (annotation.length > 1) {
throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName()); throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName());
} }
return ((Column) annotation[0]).nullable(); String name = ((Column) annotation[0]).name();
if (name.isBlank()) {
return element.getName();
}
return name;
}
public static boolean getNotNull(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class);
if (annotation.length == 0) {
return false;
}
if (annotation.length > 1) {
throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName());
}
return !((Column) annotation[0]).nullable();
} }
public static boolean isPrimaryKey(final Field element) throws Exception { public static boolean isPrimaryKey(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class);
if (annotation.length == 0) { if (annotation.length == 0) {
return true; return false;
} }
if (annotation.length > 1) { if (annotation.length > 1) {
throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName()); throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName());
@ -125,5 +140,5 @@ public class AnnotationTools {
} }
return ((GeneratedValue) annotation[0]).strategy(); return ((GeneratedValue) annotation[0]).strategy();
} }
} }

View File

@ -7,6 +7,6 @@ import java.lang.annotation.Target;
@Target(ElementType.ANNOTATION_TYPE) @Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SQLAddOn { public @interface DataAddOn {
} }

View File

@ -5,8 +5,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SQLForeignKey { public @interface SQLWhere {
String value(); String clause();
} }

View File

@ -5,11 +5,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.kar.archidata.annotation.SQLAddOn; import org.kar.archidata.annotation.DataAddOn;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@SQLAddOn @DataAddOn
public @interface SQLTableExternalForeinKeyAsList { public @interface SQLTableExternalForeinKeyAsList {
} }

View File

@ -1,28 +0,0 @@
package org.kar.archidata.annotation.addOn;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kar.archidata.annotation.SQLAddOn;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@SQLAddOn
public @interface SQLTableExternalLink {
public static String AUTOMATIC = "__auto__";
// If automatic table name, the table name is: parentTableName_externalTableName__link
String tableName() default AUTOMATIC;
// If automatic table name, the name of the foreign table is manage with the variable name.
String externalTableName() default AUTOMATIC;
// If the external link have a field to filter with a specific value (name of the field)
String filterField() default AUTOMATIC;
// If the external link have a field to filter with a specific value (value of the field)
String filterValue() default AUTOMATIC;
}

View File

@ -0,0 +1,29 @@
package org.kar.archidata.backup;
import java.util.ArrayList;
import java.util.List;
public class BackupEngine {
public enum StoreMode {
JSON, SQL
}
private final String pathStore;
private final StoreMode mode;
private List<Class<?>> classes = new ArrayList<>();
public BackupEngine(String pathToStoreDB, StoreMode mode) {
this.pathStore = pathToStoreDB;
this.mode = mode;
}
public void addClass(Class<?> clazz) {
classes.add(clazz);
}
public void store() {
// TODO ...
}
}

View File

@ -7,6 +7,7 @@ import java.util.List;
import org.kar.archidata.db.DBConfig; import org.kar.archidata.db.DBConfig;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.db.DBEntry;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper; import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -61,7 +62,7 @@ public class MigrationEngine {
return null; return null;
} }
try { try {
List<MigrationModel> data = SqlWrapper.gets(MigrationModel.class, false); List<MigrationModel> data = SqlWrapper.gets(MigrationModel.class, new QuerryOptions("SQLNotRead_disable", true));
if (data == null) { if (data == null) {
LOGGER.error("Can not collect the migration table in the DB:{}"); LOGGER.error("Can not collect the migration table in the DB:{}");
return null; return null;
@ -72,7 +73,7 @@ public class MigrationEngine {
} }
LOGGER.debug("List of migrations:"); LOGGER.debug("List of migrations:");
for (MigrationModel elem : data) { for (MigrationModel elem : data) {
LOGGER.debug(" - date={} name={} end={}", elem.modify_date, elem.name, elem.terminated); LOGGER.debug(" - date={} name={} end={}", elem.updatedAt, elem.name, elem.terminated);
} }
return data.get(data.size() - 1); return data.get(data.size() - 1);
} catch (Exception ex) { } catch (Exception ex) {
@ -111,6 +112,7 @@ public class MigrationEngine {
LOGGER.info("Verify existance of migration table '{}'", "KAR_migration"); LOGGER.info("Verify existance of migration table '{}'", "KAR_migration");
exist = SqlWrapper.isTableExist("KAR_migration"); exist = SqlWrapper.isTableExist("KAR_migration");
if (!exist) { if (!exist) {
LOGGER.info("'{}' Does not exist create a new one...", "KAR_migration");
// create the table: // create the table:
List<String> sqlQuery; List<String> sqlQuery;
try { try {

View File

@ -13,24 +13,24 @@ import org.slf4j.LoggerFactory;
public class MigrationSqlStep implements MigrationInterface { public class MigrationSqlStep implements MigrationInterface {
final static Logger LOGGER = LoggerFactory.getLogger(MigrationSqlStep.class); final static Logger LOGGER = LoggerFactory.getLogger(MigrationSqlStep.class);
private final List<String> actions = new ArrayList<>(); private final List<String> actions = new ArrayList<>();
@Override @Override
public String getName() { public String getName() {
return getClass().getCanonicalName(); return getClass().getCanonicalName();
} }
public void display() { public void display() {
for (int iii = 0; iii < this.actions.size(); iii++) { for (int iii = 0; iii < this.actions.size(); iii++) {
final String action = this.actions.get(iii); final String action = this.actions.get(iii);
LOGGER.info(" >>>> SQL ACTION : {}/{} ==> \n{}", iii, this.actions.size(), action); LOGGER.info(" >>>> SQL ACTION : {}/{} ==> \n{}", iii, this.actions.size(), action);
} }
} }
@Override @Override
public boolean applyMigration(final DBEntry entry, final StringBuilder log, final MigrationModel model) { public boolean applyMigration(final DBEntry entry, final StringBuilder log, final MigrationModel model) {
for (int iii = 0; iii < this.actions.size(); iii++) { for (int iii = 0; iii < this.actions.size(); iii++) {
log.append("action [" + iii + "/" + this.actions.size() + "]\n"); log.append("action [" + (iii + 1) + "/" + this.actions.size() + "]\n");
LOGGER.info(" >>>> SQL ACTION : {}/{}", iii, this.actions.size()); LOGGER.info(" >>>> SQL ACTION : {}/{}", iii + 1, this.actions.size());
final String action = this.actions.get(iii); final String action = this.actions.get(iii);
LOGGER.info("SQL request: ```{}```", action); LOGGER.info("SQL request: ```{}```", action);
log.append("SQL: " + action + "\n"); log.append("SQL: " + action + "\n");
@ -49,8 +49,8 @@ public class MigrationSqlStep implements MigrationInterface {
} }
return false; return false;
} }
log.append("action [" + iii + "/" + this.actions.size() + "] ==> DONE\n"); log.append("action [" + (iii + 1) + "/" + this.actions.size() + "] ==> DONE\n");
LOGGER.info(" >>>> SQL ACTION : {}/{} ==> DONE", iii, this.actions.size()); LOGGER.info(" >>>> SQL ACTION : {}/{} ==> DONE", iii + 1, this.actions.size());
model.stepId = iii + 1; model.stepId = iii + 1;
model.log = log.toString(); model.log = log.toString();
try { try {
@ -68,24 +68,24 @@ public class MigrationSqlStep implements MigrationInterface {
} }
return true; return true;
} }
@Override @Override
public boolean revertMigration(final DBEntry entry, final StringBuilder log) { public boolean revertMigration(final DBEntry entry, final StringBuilder log) {
return false; return false;
} }
public void addAction(final String action) { public void addAction(final String action) {
this.actions.add(action); this.actions.add(action);
} }
public void addClass(final Class<?> clazz) throws Exception { public void addClass(final Class<?> clazz) throws Exception {
final List<String> tmp = SqlWrapper.createTable(clazz, false); final List<String> tmp = SqlWrapper.createTable(clazz, false);
this.actions.addAll(tmp); this.actions.addAll(tmp);
} }
@Override @Override
public int getNumberOfStep() { public int getNumberOfStep() {
return this.actions.size(); return this.actions.size();
} }
} }

View File

@ -14,6 +14,7 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
//@SQLWhere(clause = "deleted=false")
public class GenericTable { public class GenericTable {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ -30,12 +31,25 @@ public class GenericTable {
@CreationTimestamp @CreationTimestamp
@Column(nullable = false) @Column(nullable = false)
@SQLComment("Create time of the object") @SQLComment("Create time of the object")
@SQLDefault("CURRENT_TIMESTAMP(3)") public Timestamp createdAt = null;
public Timestamp create_date = null;
@SQLNotRead @SQLNotRead
@UpdateTimestamp @UpdateTimestamp
@Column(nullable = false) @Column(nullable = false)
@SQLComment("When update the object") @SQLComment("When update the object")
@SQLDefault("CURRENT_TIMESTAMP(3)") public Timestamp updatedAt = null;
public Timestamp modify_date = null;
} }
/* TODO Later:
@SQLNotRead
@CreationTimestamp
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
@SQLComment("Create time of the object")
public Date createdAt = null;
@SQLNotRead
@UpdateTimestamp
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
@SQLComment("When update the object")
public Date updatedAt = null;
*/

View File

@ -19,13 +19,12 @@ import java.util.List;
import org.kar.archidata.annotation.SQLDefault; import org.kar.archidata.annotation.SQLDefault;
import org.kar.archidata.annotation.SQLIfNotExists; import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.sqlWrapper.Foreign;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Table(name = "user") @Table(name = "user")
@ -45,10 +44,10 @@ public class User extends GenericTable {
@SQLDefault("'0'") @SQLDefault("'0'")
@Column(nullable = false) @Column(nullable = false)
public boolean removed = false; public boolean removed = false;
@ManyToOne(fetch = FetchType.LAZY) @ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class)
public List<Foreign<Data>> covers; public List<Long> covers;
@Override @Override
public String toString() { public String toString() {
return "User [login=" + this.login + ", last=" + this.lastConnection + ", admin=" + this.admin + "]"; return "User [login=" + this.login + ", last=" + this.lastConnection + ", admin=" + this.admin + "]";

View File

@ -1,5 +1,7 @@
package org.kar.archidata.sqlWrapper; package org.kar.archidata.sqlWrapper;
// Mark as deprecated while the concept is not ready ...
@Deprecated
public class Foreign<T> { public class Foreign<T> {
public final Long id; public final Long id;
public final T data; public final T data;

View File

@ -1,11 +0,0 @@
package org.kar.archidata.sqlWrapper;
import org.kar.archidata.sqlWrapper.addOn.AddOnSQLTableExternalForeinKeyAsList;
import org.kar.archidata.sqlWrapper.addOn.AddOnSQLTableExternalLink;
public class GenericAddOn {
public static void addGenericAddOn() {
SqlWrapper.addAddOn(new AddOnSQLTableExternalLink());
SqlWrapper.addAddOn(new AddOnSQLTableExternalForeinKeyAsList());
}
}

View File

@ -19,8 +19,10 @@ public class QuerryAnd implements QuerryItem {
} }
public void generateQuerry(StringBuilder querry, String tableName) { public void generateQuerry(StringBuilder querry, String tableName) {
querry.append(" ("); if (this.childs.size() >= 1) {
boolean first = false; querry.append(" (");
}
boolean first = true;
for (QuerryItem elem : this.childs) { for (QuerryItem elem : this.childs) {
if (first) { if (first) {
first = false; first = false;
@ -29,7 +31,9 @@ public class QuerryAnd implements QuerryItem {
} }
elem.generateQuerry(querry, tableName); elem.generateQuerry(querry, tableName);
} }
querry.append(")"); if (this.childs.size() >= 1) {
querry.append(")");
}
} }
@Override @Override

View File

@ -0,0 +1,35 @@
package org.kar.archidata.sqlWrapper;
import java.util.HashMap;
import java.util.Map;
public class QuerryOptions {
private final Map<String, Object> options = new HashMap<>();
public QuerryOptions() {
}
public QuerryOptions(String key, Object value) {
options.put(key, value);
}
public QuerryOptions(String key, Object value, String key2, Object value2) {
options.put(key, value);
options.put(key2, value2);
}
public QuerryOptions(String key, Object value, String key2, Object value2, String key3, Object value3) {
options.put(key, value);
options.put(key2, value2);
options.put(key3, value3);
}
public void put(String key, Object value) {
options.put(key, value);
}
public Object get(String value) {
return options.get(value);
}
}

View File

@ -11,8 +11,10 @@ public class QuerryOr implements QuerryItem {
} }
public void generateQuerry(StringBuilder querry, String tableName) { public void generateQuerry(StringBuilder querry, String tableName) {
querry.append(" ("); if (this.childs.size() >= 1) {
boolean first = false; querry.append(" (");
}
boolean first = true;
for (QuerryItem elem : this.childs) { for (QuerryItem elem : this.childs) {
if (first) { if (first) {
first = false; first = false;
@ -21,7 +23,9 @@ public class QuerryOr implements QuerryItem {
} }
elem.generateQuerry(querry, tableName); elem.generateQuerry(querry, tableName);
} }
querry.append(")"); if (this.childs.size() >= 1) {
querry.append(")");
}
} }
@Override @Override

View File

@ -18,13 +18,16 @@ import java.util.List;
import org.kar.archidata.GlobalConfiguration; import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.CreationTimestamp; import org.kar.archidata.annotation.CreationTimestamp;
import org.kar.archidata.annotation.SQLAddOn; import org.kar.archidata.annotation.DataAddOn;
import org.kar.archidata.annotation.SQLDefault; import org.kar.archidata.annotation.SQLDefault;
import org.kar.archidata.annotation.SQLDeleted; import org.kar.archidata.annotation.SQLDeleted;
import org.kar.archidata.annotation.SQLIfNotExists; import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLNotRead; import org.kar.archidata.annotation.SQLNotRead;
import org.kar.archidata.annotation.UpdateTimestamp; import org.kar.archidata.annotation.UpdateTimestamp;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.db.DBEntry;
import org.kar.archidata.sqlWrapper.addOn.AddOnManyToMany;
import org.kar.archidata.sqlWrapper.addOn.AddOnManyToOne;
import org.kar.archidata.sqlWrapper.addOn.AddOnSQLTableExternalForeinKeyAsList;
import org.kar.archidata.util.ConfigBaseVariable; import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -33,30 +36,38 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.InternalServerErrorException;
public class SqlWrapper { public class SqlWrapper {
static final Logger LOGGER = LoggerFactory.getLogger(SqlWrapper.class); static final Logger LOGGER = LoggerFactory.getLogger(SqlWrapper.class);
static final List<SqlWrapperAddOn> addOn = new ArrayList<>(); static final List<SqlWrapperAddOn> addOn = new ArrayList<>();
static {
addOn.add(new AddOnManyToMany());
addOn.add(new AddOnManyToOne());
addOn.add(new AddOnSQLTableExternalForeinKeyAsList());
}
public static void addAddOn(final SqlWrapperAddOn addOn) { public static void addAddOn(final SqlWrapperAddOn addOn) {
SqlWrapper.addOn.add(addOn); SqlWrapper.addOn.add(addOn);
}; };
public static class ExceptionDBInterface extends Exception { public static class ExceptionDBInterface extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public int errorID; public int errorID;
public ExceptionDBInterface(final int errorId, final String message) { public ExceptionDBInterface(final int errorId, final String message) {
super(message); super(message);
this.errorID = errorId; this.errorID = errorId;
} }
} }
public SqlWrapper() { public SqlWrapper() {
} }
public static boolean isDBExist(final String name) throws InternalServerErrorException { public static boolean isDBExist(final String name) throws InternalServerErrorException {
if (ConfigBaseVariable.getDBType().equals("sqlite")) { if (ConfigBaseVariable.getDBType().equals("sqlite")) {
// no base manage in sqLite ... // no base manage in sqLite ...
@ -98,7 +109,7 @@ public class SqlWrapper {
} }
throw new InternalServerErrorException("Can Not manage the DB-access"); throw new InternalServerErrorException("Can Not manage the DB-access");
} }
public static boolean createDB(final String name) { public static boolean createDB(final String name) {
if (ConfigBaseVariable.getDBType().equals("sqlite")) { if (ConfigBaseVariable.getDBType().equals("sqlite")) {
// no base manage in sqLite ... // no base manage in sqLite ...
@ -117,7 +128,7 @@ public class SqlWrapper {
return false; return false;
} }
} }
public static boolean isTableExist(final String name) throws InternalServerErrorException { public static boolean isTableExist(final String name) throws InternalServerErrorException {
try { try {
String request = ""; String request = "";
@ -157,7 +168,7 @@ public class SqlWrapper {
} }
throw new InternalServerErrorException("Can Not manage the DB-access"); throw new InternalServerErrorException("Can Not manage the DB-access");
} }
public static String convertTypeInSQL(final Class<?> type) throws Exception { public static String convertTypeInSQL(final Class<?> type) throws Exception {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) { if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
if (type == Long.class || type == long.class) { if (type == Long.class || type == long.class) {
@ -212,7 +223,7 @@ public class SqlWrapper {
} }
throw new Exception("Imcompatible type of element in object for: " + type.getCanonicalName()); throw new Exception("Imcompatible type of element in object for: " + type.getCanonicalName());
} }
protected static <T> void setValuedb(final Class<?> type, final T data, int index, final Field field, final PreparedStatement ps) protected static <T> void setValuedb(final Class<?> type, final T data, int index, final Field field, final PreparedStatement ps)
throws IllegalArgumentException, IllegalAccessException, SQLException { throws IllegalArgumentException, IllegalAccessException, SQLException {
if (type == Long.class) { if (type == Long.class) {
@ -283,7 +294,7 @@ public class SqlWrapper {
} }
} }
} }
protected static <T> void setValueFromDb(final Class<?> type, final T data, final int index, final Field field, final ResultSet rs) protected static <T> void setValueFromDb(final Class<?> type, final T data, final int index, final Field field, final ResultSet rs)
throws IllegalArgumentException, IllegalAccessException, SQLException { throws IllegalArgumentException, IllegalAccessException, SQLException {
if (type == Long.class) { if (type == Long.class) {
@ -380,11 +391,22 @@ public class SqlWrapper {
} }
} }
} }
public static boolean isAddOnField(final Field field) { public static boolean isAddOnField(final Field field) {
return AnnotationTools.isAnnotationGroup(field, SQLAddOn.class); boolean ret = AnnotationTools.isAnnotationGroup(field, DataAddOn.class);
if (ret == true) {
return true;
}
// The specific element of the JPA manage fy generic add-on system:
if (field.getDeclaredAnnotationsByType(ManyToMany.class).length != 0) {
return true;
}
if (field.getDeclaredAnnotationsByType(ManyToOne.class).length != 0) {
return true;
}
return ret;
} }
public static SqlWrapperAddOn findAddOnforField(final Field field) { public static SqlWrapperAddOn findAddOnforField(final Field field) {
for (final SqlWrapperAddOn elem : addOn) { for (final SqlWrapperAddOn elem : addOn) {
if (elem.isCompatibleField(field)) { if (elem.isCompatibleField(field)) {
@ -393,11 +415,11 @@ public class SqlWrapper {
} }
return null; return null;
} }
public static <T> T insert(final T data) throws Exception { public static <T> T insert(final T data) throws Exception {
final Class<?> clazz = data.getClass(); final Class<?> clazz = data.getClass();
//public static NodeSmall createNode(String typeInNode, String name, String descrition, Long parentId) { //public static NodeSmall createNode(String typeInNode, String name, String descrition, Long parentId) {
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
// real add in the BDD: // real add in the BDD:
try { try {
@ -407,7 +429,7 @@ public class SqlWrapper {
querry.append("INSERT INTO `"); querry.append("INSERT INTO `");
querry.append(tableName); querry.append(tableName);
querry.append("` ("); querry.append("` (");
boolean firstField = true; boolean firstField = true;
int count = 0; int count = 0;
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
@ -437,7 +459,7 @@ public class SqlWrapper {
} }
} }
count++; count++;
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
if (firstField) { if (firstField) {
firstField = false; firstField = false;
} else { } else {
@ -537,16 +559,16 @@ public class SqlWrapper {
} }
return data; return data;
} }
// seems a good idea, but very dangerous if we not filter input data... if set an id it can be complicated... // seems a good idea, but very dangerous if we not filter input data... if set an id it can be complicated...
public static <T> T insertWithJson(final Class<T> clazz, final String jsonData) throws Exception { public static <T> T insertWithJson(final Class<T> clazz, final String jsonData) throws Exception {
final ObjectMapper mapper = new ObjectMapper(); final ObjectMapper mapper = new ObjectMapper();
// parse the object to be sure the data are valid: // parse the object to be sure the data are valid:
final T data = mapper.readValue(jsonData, clazz); final T data = mapper.readValue(jsonData, clazz);
return insert(data); return insert(data);
} }
public static <T> int update(final Class<T> clazz, final long id, final String jsonData) throws Exception { public static <T> int update(final Class<T> clazz, final long id, final String jsonData) throws Exception {
final ObjectMapper mapper = new ObjectMapper(); final ObjectMapper mapper = new ObjectMapper();
// parse the object to be sure the data are valid: // parse the object to be sure the data are valid:
@ -558,7 +580,7 @@ public class SqlWrapper {
iterator.forEachRemaining(e -> keys.add(e)); iterator.forEachRemaining(e -> keys.add(e));
return update(data, id, keys); return update(data, id, keys);
} }
/** /**
* *
* @param <T> * @param <T>
@ -571,7 +593,7 @@ public class SqlWrapper {
public static <T> int update(final T data, final long id, final List<String> filterValue) throws Exception { public static <T> int update(final T data, final long id, final List<String> filterValue) throws Exception {
final Class<?> clazz = data.getClass(); final Class<?> clazz = data.getClass();
//public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) { //public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) {
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
// real add in the BDD: // real add in the BDD:
try { try {
@ -581,7 +603,7 @@ public class SqlWrapper {
querry.append("UPDATE `"); querry.append("UPDATE `");
querry.append(tableName); querry.append(tableName);
querry.append("` SET "); querry.append("` SET ");
boolean firstField = true; boolean firstField = true;
Field primaryKeyField = null; Field primaryKeyField = null;
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
@ -601,7 +623,7 @@ public class SqlWrapper {
if (createTime) { if (createTime) {
continue; continue;
} }
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (!updateTime && !filterValue.contains(name)) { if (!updateTime && !filterValue.contains(name)) {
continue; continue;
@ -628,7 +650,7 @@ public class SqlWrapper {
} }
} }
querry.append(" WHERE `"); querry.append(" WHERE `");
querry.append(primaryKeyField.getName()); querry.append(AnnotationTools.getFieldName(primaryKeyField));
querry.append("` = ?"); querry.append("` = ?");
firstField = true; firstField = true;
// logger.debug("generate the querry: '{}'", querry.toString()); // logger.debug("generate the querry: '{}'", querry.toString());
@ -651,7 +673,7 @@ public class SqlWrapper {
if (createTime) { if (createTime) {
continue; continue;
} }
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (updateTime || !filterValue.contains(name)) { if (updateTime || !filterValue.contains(name)) {
continue; continue;
@ -681,7 +703,7 @@ public class SqlWrapper {
} }
return 0; return 0;
} }
static void addElement(final PreparedStatement ps, final Object value, final int iii) throws Exception { static void addElement(final PreparedStatement ps, final Object value, final int iii) throws Exception {
if (value.getClass() == Long.class) { if (value.getClass() == Long.class) {
ps.setLong(iii, (Long) value); ps.setLong(iii, (Long) value);
@ -709,32 +731,19 @@ public class SqlWrapper {
throw new Exception("Not manage type ==> need to add it ..."); throw new Exception("Not manage type ==> need to add it ...");
} }
} }
public static <T> T getWhere(final Class<T> clazz, final QuerryItem condition) throws Exception { public static void whereAppendQuery(final StringBuilder querry, final String tableName, final QuerryItem condition, final QuerryOptions options) throws ExceptionDBInterface {
return getWhere(clazz, condition, false); boolean exclude_deleted = true;
} if (options != null) {
Object data = options.get("SQLDeleted_disable");
public static <T> T getWhere(final Class<T> clazz, final QuerryItem condition, final boolean full) throws Exception { if (data instanceof Boolean elem) {
final List<T> values = getsWhere(clazz, condition, full, 1); exclude_deleted = !(elem == true);
if (values.size() == 0) { } else {
return null; if (data != null) {
LOGGER.error("'SQLDeleted_disable' ==> has not a boolean value: {}", data);
}
}
} }
return values.get(0);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition) throws Exception {
return getsWhere(clazz, condition, null, false, null);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final boolean full) throws Exception {
return getsWhere(clazz, condition, null, full, null);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final boolean full, final Integer linit) throws Exception {
return getsWhere(clazz, condition, null, full, linit);
}
public static void whereAppendQuery(final StringBuilder querry, final String tableName, final QuerryItem condition, final boolean exclude_deleted) throws ExceptionDBInterface {
// Check if we have a condition to generate // Check if we have a condition to generate
if (condition == null) { if (condition == null) {
if (exclude_deleted) { if (exclude_deleted) {
@ -746,7 +755,7 @@ public class SqlWrapper {
} }
querry.append(" WHERE ("); querry.append(" WHERE (");
condition.generateQuerry(querry, tableName); condition.generateQuerry(querry, tableName);
querry.append(") "); querry.append(") ");
if (exclude_deleted) { if (exclude_deleted) {
querry.append("AND "); querry.append("AND ");
@ -754,7 +763,7 @@ public class SqlWrapper {
querry.append(".deleted = false "); querry.append(".deleted = false ");
} }
} }
public static void whereInjectValue(final PreparedStatement ps, final QuerryItem condition) throws Exception { public static void whereInjectValue(final PreparedStatement ps, final QuerryItem condition) throws Exception {
// Check if we have a condition to generate // Check if we have a condition to generate
if (condition == null) { if (condition == null) {
@ -763,29 +772,67 @@ public class SqlWrapper {
int iii = 1; int iii = 1;
iii = condition.injectQuerry(ps, iii); iii = condition.injectQuerry(ps, iii);
} }
public static int executeSimpleQuerry(final String querry, final boolean root) throws SQLException, IOException { public static int executeSimpleQuerry(final String querry, final boolean root) throws SQLException, IOException {
final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig, root); final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig, root);
final Statement stmt = entry.connection.createStatement(); final Statement stmt = entry.connection.createStatement();
return stmt.executeUpdate(querry); return stmt.executeUpdate(querry);
} }
public static int executeSimpleQuerry(final String querry) throws SQLException, IOException { public static int executeSimpleQuerry(final String querry) throws SQLException, IOException {
return executeSimpleQuerry(querry, false); return executeSimpleQuerry(querry, false);
} }
public static boolean executeQuerry(final String querry, final boolean root) throws SQLException, IOException { public static boolean executeQuerry(final String querry, final boolean root) throws SQLException, IOException {
final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig, root); final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig, root);
final Statement stmt = entry.connection.createStatement(); final Statement stmt = entry.connection.createStatement();
return stmt.execute(querry); return stmt.execute(querry);
} }
public static boolean executeQuerry(final String querry) throws SQLException, IOException { public static boolean executeQuerry(final String querry) throws SQLException, IOException {
return executeQuerry(querry, false); return executeQuerry(querry, false);
} }
public static <T> T getWhere(final Class<T> clazz, final QuerryItem condition) throws Exception {
return getWhere(clazz, condition, null);
}
public static <T> T getWhere(final Class<T> clazz, final QuerryItem condition, final QuerryOptions options) throws Exception {
final List<T> values = getsWhere(clazz, condition, options, 1);
if (values.size() == 0) {
return null;
}
return values.get(0);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition) throws Exception {
return getsWhere(clazz, condition, null, null, null);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final QuerryOptions options) throws Exception {
return getsWhere(clazz, condition, null, options, null);
}
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final QuerryOptions options, final Integer linit) throws Exception {
return getsWhere(clazz, condition, null, options, linit);
}
// TODO: set limit as an querry Option...
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final String orderBy, final boolean full, final Integer linit) throws Exception { public static <T> List<T> getsWhere(final Class<T> clazz, final QuerryItem condition, final String orderBy, final QuerryOptions options, final Integer linit) throws Exception {
boolean readAllfields = false;
if (options != null) {
Object data = options.get("SQLNotRead_disable");
if (data instanceof Boolean elem) {
readAllfields = elem;
} else {
if (data != null) {
LOGGER.error("'SQLNotRead_disable' ==> has not a boolean value: {}", data);
}
}
}
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
final List<T> outs = new ArrayList<>(); final List<T> outs = new ArrayList<>();
// real add in the BDD: // real add in the BDD:
@ -796,7 +843,7 @@ public class SqlWrapper {
querry.append("SELECT "); querry.append("SELECT ");
//querry.append(tableName); //querry.append(tableName);
//querry.append(" SET "); //querry.append(" SET ");
boolean firstField = true; boolean firstField = true;
int count = 0; int count = 0;
boolean hasDeleted = false; boolean hasDeleted = false;
@ -809,18 +856,15 @@ public class SqlWrapper {
if (addOn != null) { if (addOn != null) {
continue; continue;
} }
final boolean createTime = elem.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; // TODO: Manage it with AddOn
if (!full && createTime) { final boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0;
if (!readAllfields && notRead) {
continue; continue;
} }
if (!hasDeleted) { if (!hasDeleted) {
hasDeleted = elem.getDeclaredAnnotationsByType(SQLDeleted.class).length != 0; hasDeleted = elem.getDeclaredAnnotationsByType(SQLDeleted.class).length != 0;
} }
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (!full && updateTime) {
continue;
}
count++; count++;
if (firstField) { if (firstField) {
firstField = false; firstField = false;
@ -830,13 +874,13 @@ public class SqlWrapper {
querry.append(" "); querry.append(" ");
querry.append(tableName); querry.append(tableName);
querry.append("."); querry.append(".");
querry.append(name); querry.append(name);
} }
querry.append(" FROM `"); querry.append(" FROM `");
querry.append(tableName); querry.append(tableName);
querry.append("` "); querry.append("` ");
whereAppendQuery(querry, tableName, condition, firstField); whereAppendQuery(querry, tableName, condition, options);
if (orderBy != null && orderBy.length() >= 1) { if (orderBy != null && orderBy.length() >= 1) {
querry.append(" ORDER BY "); querry.append(" ORDER BY ");
//querry.append(tableName); //querry.append(tableName);
@ -865,13 +909,9 @@ public class SqlWrapper {
if (addOn != null) { if (addOn != null) {
continue; continue;
} }
final boolean createTime = elem.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; // TODO: Manage it with AddOn
if (!full && createTime) { final boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0;
continue; if (!readAllfields && notRead) {
}
//String name = elem.getName();
final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (!full && updateTime) {
continue; continue;
} }
setValueFromDb(elem.getType(), data, count, elem, rs); setValueFromDb(elem.getType(), data, count, elem, rs);
@ -880,9 +920,10 @@ public class SqlWrapper {
final T out = (T) data; final T out = (T) data;
outs.add(out); outs.add(out);
} }
} catch (final SQLException ex) { } catch (final SQLException ex) {
ex.printStackTrace(); ex.printStackTrace();
throw ex;
} catch (final Exception ex) { } catch (final Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
@ -891,7 +932,8 @@ public class SqlWrapper {
} }
return outs; return outs;
} }
// TODO : detect the @Id
public static <T> T get(final Class<T> clazz, final long id) throws Exception { public static <T> T get(final Class<T> clazz, final long id) throws Exception {
Field primaryKeyField = null; Field primaryKeyField = null;
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
@ -904,145 +946,66 @@ public class SqlWrapper {
} }
} }
if (primaryKeyField != null) { if (primaryKeyField != null) {
return SqlWrapper.getWhere(clazz, new QuerryCondition(primaryKeyField.getName(), "=", id), false); return SqlWrapper.getWhere(clazz, new QuerryCondition(AnnotationTools.getFieldName(primaryKeyField), "=", id));
} }
throw new Exception("Missing primary Key..."); throw new Exception("Missing primary Key...");
} }
public static String getCurrentTimeStamp() { public static String getCurrentTimeStamp() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")); return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
} }
public static <T> List<T> gets(final Class<T> clazz, final boolean full) throws Exception { public static <T> List<T> gets(final Class<T> clazz) throws Exception {
LOGGER.debug("request get {} start @{}", clazz.getCanonicalName(), getCurrentTimeStamp()); return getsWhere(clazz, null);
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); }
final List<T> out = new ArrayList<>();
// real add in the BDD: public static <T> List<T> gets(final Class<T> clazz, final QuerryOptions options) throws Exception {
return getsWhere(clazz, null, options);
}
public static boolean hasDeletedField(final Class<?> clazz) throws Exception {
try { try {
final String tableName = AnnotationTools.getTableName(clazz);
//boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
final StringBuilder querry = new StringBuilder();
querry.append("SELECT ");
boolean firstField = true;
int count = 0;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! A revoir, il faut faire une liste dynamique qui dépend des add_ons....
//StateLoad[] autoClasify = new StateLoad[clazz.getFields().length];
final List<StateLoad> autoClasify = new ArrayList<>();
int indexAutoClasify = 0;
boolean hasDeleted = false; boolean hasDeleted = false;
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
// static field is only for internal global declaration ==> remove it .. // static field is only for internal global declaration ==> remove it ..
if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) { if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
continue; continue;
} }
final boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0; if (elem.getDeclaredAnnotationsByType(SQLDeleted.class).length != 0) {
if (!full && notRead) { return true;
autoClasify.add(StateLoad.DISABLE);
continue;
}
if (!hasDeleted) {
hasDeleted = elem.getDeclaredAnnotationsByType(SQLDeleted.class).length != 0;
}
final String name = elem.getName();
if (firstField) {
firstField = false;
} else {
querry.append(",");
}
final SqlWrapperAddOn addOn = findAddOnforField(elem);
if (addOn != null) {
count += addOn.generateQuerry(tableName, elem, querry, name, autoClasify);
} else {
count++;
autoClasify.add(StateLoad.NORMAL);
querry.append(" ");
querry.append(tableName);
querry.append(".");
querry.append(name);
} }
} }
querry.append(" FROM `"); } catch (final Exception ex) {
querry.append(tableName);
querry.append("` ");
if (hasDeleted) {
querry.append(" WHERE ");
//querry.append(tableName);
//querry.append(".");
//querry.append(primaryKeyField.getName());
//querry.append(" = ?");
//querry.append(" AND ");
querry.append(tableName);
querry.append(".deleted = false ");
}
firstField = true;
LOGGER.debug("generate the querry: '{}'", querry.toString());
LOGGER.debug("request get {} prepare @{}", clazz.getCanonicalName(), getCurrentTimeStamp());
// prepare the request:
final PreparedStatement ps = entry.connection.prepareStatement(querry.toString(), Statement.RETURN_GENERATED_KEYS);
LOGGER.debug("request get {} querry @{}", clazz.getCanonicalName(), getCurrentTimeStamp());
// execute the request
final ResultSet rs = ps.executeQuery();
LOGGER.debug("request get {} transform @{}", clazz.getCanonicalName(), getCurrentTimeStamp());
while (rs.next()) {
indexAutoClasify = 0;
final Object data = clazz.getConstructors()[0].newInstance();
count = 1;
for (final Field elem : clazz.getFields()) {
if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
continue;
}
/*
boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0;
*/
final boolean notRead = autoClasify.get(indexAutoClasify) == StateLoad.DISABLE;
if (!full && notRead) {
indexAutoClasify++;
continue;
}
//String name = elem.getName();
//boolean linkGeneric = elem.getDeclaredAnnotationsByType(SQLTableLinkGeneric.class).length != 0;
final SqlWrapperAddOn addOn = findAddOnforField(elem);
if (addOn != null) {
count += addOn.fillFromQuerry(rs, elem, data, count);
} else {
setValueFromDb(elem.getType(), data, count, elem, rs);
count++;
}
indexAutoClasify++;
}
//logger.debug("Read: {}", (T)data);
out.add((T) data);
}
LOGGER.debug("request get {} ready @{}", clazz.getCanonicalName(), getCurrentTimeStamp());
} catch (final SQLException ex) {
ex.printStackTrace(); ex.printStackTrace();
} finally {
entry.close();
entry = null;
} }
return out; return false;
} }
// TODO : detect the @Id
public static void delete(final Class<?> clazz, final long id) throws Exception { public static void delete(final Class<?> clazz, final long id) throws Exception {
// TODO: I am not sure this is a real good idea. boolean hasDeleted = hasDeletedField(clazz);
if (hasDeleted == true) {
deleteSoft(clazz, id);
} else {
deleteHard(clazz, id);
}
} }
public static int setDelete(final Class<?> clazz, final long id) throws Exception { public static void deleteHard(final Class<?> clazz, final long id) throws Exception {
throw new Exception("Not implemented delete hard ...");
}
private static int deleteSoft(final Class<?> clazz, final long id) throws Exception {
return setDeleteWhere(clazz, new QuerryCondition("id", "=", id)); return setDeleteWhere(clazz, new QuerryCondition("id", "=", id));
} }
public static String getDBNow() { public static String getDBNow() {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) { if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
return "now(3)"; return "now(3)";
} }
return "DATE()"; return "DATE()";
} }
public static int setDeleteWhere(final Class<?> clazz, final QuerryItem condition) throws Exception { public static int setDeleteWhere(final Class<?> clazz, final QuerryItem condition) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz); final String tableName = AnnotationTools.getTableName(clazz);
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
@ -1052,7 +1015,7 @@ public class SqlWrapper {
querry.append("` SET `modify_date`="); querry.append("` SET `modify_date`=");
querry.append(getDBNow()); querry.append(getDBNow());
querry.append(", `deleted`=true "); querry.append(", `deleted`=true ");
whereAppendQuery(querry, tableName, condition, false); whereAppendQuery(querry, tableName, condition, null);
try { try {
final PreparedStatement ps = entry.connection.prepareStatement(querry.toString()); final PreparedStatement ps = entry.connection.prepareStatement(querry.toString());
whereInjectValue(ps, condition); whereInjectValue(ps, condition);
@ -1063,21 +1026,28 @@ public class SqlWrapper {
entry = null; entry = null;
} }
} }
public static int unsetDelete(final Class<?> clazz, final long id) throws Exception { public static int unsetDelete(final Class<?> clazz, final long id) throws Exception {
return unsetDeleteWhere(clazz, new QuerryCondition("id", "=", id)); return unsetDeleteWhere(clazz, new QuerryCondition("id", "=", id));
} }
public static int unsetDeleteWhere(final Class<?> clazz, final QuerryItem condition) throws Exception { public static int unsetDeleteWhere(final Class<?> clazz, final QuerryItem condition) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz); final String tableName = AnnotationTools.getTableName(clazz);
DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
final StringBuilder querry = new StringBuilder(); final StringBuilder querry = new StringBuilder();
querry.append("UPDATE `"); querry.append("UPDATE `");
querry.append(tableName); querry.append(tableName);
querry.append("` SET `modify_date`="); querry.append("` SET ");
/*
* is is needed only for SQLite ???
querry.append("`modify_date`=");
querry.append(getDBNow()); querry.append(getDBNow());
querry.append(", `deleted`=false "); querry.append(", ");
whereAppendQuery(querry, tableName, condition, false); */
querry.append("`deleted`=false ");
// need to disable the deleted false because the model must be unselected to be updated.
QuerryOptions options = new QuerryOptions("SQLDeleted_disable", true);
whereAppendQuery(querry, tableName, condition, options);
try { try {
final PreparedStatement ps = entry.connection.prepareStatement(querry.toString()); final PreparedStatement ps = entry.connection.prepareStatement(querry.toString());
whereInjectValue(ps, condition); whereInjectValue(ps, condition);
@ -1088,25 +1058,25 @@ public class SqlWrapper {
entry = null; entry = null;
} }
} }
public static List<String> createTable(final Class<?> clazz) throws Exception { public static List<String> createTable(final Class<?> clazz) throws Exception {
return createTable(clazz, true); return createTable(clazz, true);
} }
public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> ListOtherTables, final boolean createIfNotExist, public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> ListOtherTables, final boolean createIfNotExist,
final boolean createDrop, final int fieldId, final Class<?> classModel) throws Exception { final boolean createDrop, final int fieldId, final Class<?> classModel) throws Exception {
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
final Integer limitSize = AnnotationTools.getLimitSize(elem); final Integer limitSize = AnnotationTools.getLimitSize(elem);
final boolean notNull = AnnotationTools.getNotNull(elem); final boolean notNull = AnnotationTools.getNotNull(elem);
final boolean primaryKey = AnnotationTools.isPrimaryKey(elem); final boolean primaryKey = AnnotationTools.isPrimaryKey(elem);
final GenerationType strategy = AnnotationTools.getStrategy(elem); final GenerationType strategy = AnnotationTools.getStrategy(elem);
final boolean createTime = elem.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; final boolean createTime = elem.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0;
final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; final boolean updateTime = elem.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
final String comment = AnnotationTools.getComment(elem); final String comment = AnnotationTools.getComment(elem);
final String defaultValue = AnnotationTools.getDefault(elem); final String defaultValue = AnnotationTools.getDefault(elem);
if (fieldId == 0) { if (fieldId == 0) {
mainTableBuilder.append("\n\t\t`"); mainTableBuilder.append("\n\t\t`");
} else { } else {
@ -1168,11 +1138,13 @@ public class SqlWrapper {
} }
} else if (defaultValue == null) { } else if (defaultValue == null) {
if (updateTime || createTime) { if (updateTime || createTime) {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) { if (ConfigBaseVariable.getDBType().equals("sqlite")) {
mainTableBuilder.append("DEFAULT CURRENT_TIMESTAMP "); mainTableBuilder.append("DEFAULT CURRENT_TIMESTAMP ");
} else { } else {
mainTableBuilder.append("DEFAULT CURRENT_TIMESTAMP(3) "); mainTableBuilder.append("DEFAULT CURRENT_TIMESTAMP(3) ");
} }
} else if (primaryKey) {
mainTableBuilder.append("NOT NULL ");
} else { } else {
mainTableBuilder.append("DEFAULT NULL "); mainTableBuilder.append("DEFAULT NULL ");
} }
@ -1180,11 +1152,11 @@ public class SqlWrapper {
mainTableBuilder.append("DEFAULT "); mainTableBuilder.append("DEFAULT ");
mainTableBuilder.append(defaultValue); mainTableBuilder.append(defaultValue);
mainTableBuilder.append(" "); mainTableBuilder.append(" ");
} }
if (primaryKey && ConfigBaseVariable.getDBType().equals("sqlite")) { if (primaryKey && ConfigBaseVariable.getDBType().equals("sqlite")) {
mainTableBuilder.append("PRIMARY KEY "); mainTableBuilder.append("PRIMARY KEY ");
} }
if (strategy == GenerationType.IDENTITY) { if (strategy == GenerationType.IDENTITY) {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) { if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
@ -1195,14 +1167,14 @@ public class SqlWrapper {
} else if (strategy != null) { } else if (strategy != null) {
throw new Exception("Can not generate a stategy different of IDENTITY"); throw new Exception("Can not generate a stategy different of IDENTITY");
} }
if (comment != null && !ConfigBaseVariable.getDBType().equals("sqlite")) { if (comment != null && !ConfigBaseVariable.getDBType().equals("sqlite")) {
mainTableBuilder.append("COMMENT '"); mainTableBuilder.append("COMMENT '");
mainTableBuilder.append(comment.replace('\'', '\'')); mainTableBuilder.append(comment.replace('\'', '\''));
mainTableBuilder.append("' "); mainTableBuilder.append("' ");
} }
} }
public static List<String> createTable(final Class<?> clazz, final boolean createDrop) throws Exception { public static List<String> createTable(final Class<?> clazz, final boolean createDrop) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz); final String tableName = AnnotationTools.getTableName(clazz);
final boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0; final boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
@ -1227,7 +1199,7 @@ public class SqlWrapper {
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
// DEtect the primary key (support only one primary key right now... // DEtect the primary key (support only one primary key right now...
if (AnnotationTools.isPrimaryKey(elem)) { if (AnnotationTools.isPrimaryKey(elem)) {
primaryKeys.add(elem.getName()); primaryKeys.add(AnnotationTools.getFieldName(elem));
} }
} }
@ -1238,14 +1210,14 @@ public class SqlWrapper {
} }
if (isAddOnField(elem)) { if (isAddOnField(elem)) {
final SqlWrapperAddOn addOn = findAddOnforField(elem); final SqlWrapperAddOn addOn = findAddOnforField(elem);
LOGGER.info("Create type for: {} ==> {} (ADD-ON)", elem.getName(), elem.getType()); LOGGER.info("Create type for: {} ==> {} (ADD-ON)", AnnotationTools.getFieldName(elem), elem.getType());
if (addOn != null) { if (addOn != null) {
addOn.createTables(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId); addOn.createTables(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId);
} else { } else {
throw new Exception("Element matked as add-on but add-on does not loaded: table:" + tableName + " field name=" + elem.getName() + " type=" + elem.getType()); throw new Exception("Element matked as add-on but add-on does not loaded: table:" + tableName + " field name=" + AnnotationTools.getFieldName(elem) + " type=" + elem.getType());
} }
} else { } else {
LOGGER.info("Create type for: {} ==> {}", elem.getName(), elem.getType()); LOGGER.info("Create type for: {} ==> {}", AnnotationTools.getFieldName(elem), elem.getType());
SqlWrapper.createTablesSpecificType(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId, elem.getType()); SqlWrapper.createTablesSpecificType(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId, elem.getType());
} }
fieldId++; fieldId++;
@ -1268,5 +1240,5 @@ public class SqlWrapper {
outList.add(out.toString()); outList.add(out.toString());
return outList; return outList;
} }
} }

View File

@ -32,9 +32,9 @@ public interface SqlWrapperAddOn {
// External mean that the type of the object is absolutely not obvious... // External mean that the type of the object is absolutely not obvious...
boolean isExternal(); boolean isExternal();
int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List<StateLoad> autoClasify); int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List<StateLoad> autoClasify, QuerryOptions options);
int fillFromQuerry(ResultSet rs, Field elem, Object data, int count) throws SQLException, IllegalArgumentException, IllegalAccessException; int fillFromQuerry(ResultSet rs, Field elem, Object data, int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException;
boolean canUpdate(); boolean canUpdate();

View File

@ -12,8 +12,8 @@ import java.util.stream.Collectors;
import org.kar.archidata.GlobalConfiguration; import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.addOn.SQLTableExternalLink;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.db.DBEntry;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper; import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapper.ExceptionDBInterface; import org.kar.archidata.sqlWrapper.SqlWrapper.ExceptionDBInterface;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn; import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
@ -22,8 +22,10 @@ import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class AddOnSQLTableExternalLink implements SqlWrapperAddOn { import jakarta.persistence.ManyToMany;
static final Logger LOGGER = LoggerFactory.getLogger(AddOnSQLTableExternalLink.class);
public class AddOnManyToMany implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
/** /**
* Convert the list if external id in a string '-' separated * Convert the list if external id in a string '-' separated
@ -58,17 +60,17 @@ public class AddOnSQLTableExternalLink implements SqlWrapperAddOn {
@Override @Override
public Class<?> getAnnotationClass() { public Class<?> getAnnotationClass() {
return SQLTableExternalLink.class; return ManyToMany.class;
} }
@Override @Override
public String getSQLFieldType(final Field elem) { public String getSQLFieldType(final Field elem) {
return "STRING"; return null;
} }
@Override @Override
public boolean isCompatibleField(final Field elem) { public boolean isCompatibleField(final Field elem) {
final SQLTableExternalLink decorators = elem.getDeclaredAnnotation(SQLTableExternalLink.class); final ManyToMany decorators = elem.getDeclaredAnnotation(ManyToMany.class);
return decorators != null; return decorators != null;
} }
@ -92,7 +94,7 @@ public class AddOnSQLTableExternalLink implements SqlWrapperAddOn {
} }
@Override @Override
public int generateQuerry(final String tableName, final Field elem, final StringBuilder querry, final String name, final List<StateLoad> autoClasify) { public int generateQuerry(final String tableName, final Field elem, final StringBuilder querry, final String name, final List<StateLoad> autoClasify, QuerryOptions options) {
autoClasify.add(StateLoad.ARRAY); autoClasify.add(StateLoad.ARRAY);
String localName = name; String localName = name;
@ -136,7 +138,7 @@ public class AddOnSQLTableExternalLink implements SqlWrapperAddOn {
} }
@Override @Override
public int fillFromQuerry(final ResultSet rs, final Field elem, final Object data, final int count) throws SQLException, IllegalArgumentException, IllegalAccessException { public int fillFromQuerry(final ResultSet rs, final Field elem, final Object data, final int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
throw new IllegalAccessException("This Add-on has not the capability to insert data directly in DB"); throw new IllegalAccessException("This Add-on has not the capability to insert data directly in DB");
} }
@ -204,10 +206,11 @@ public class AddOnSQLTableExternalLink implements SqlWrapperAddOn {
} }
} }
// TODO : refacto this table to manage a generic table with dynamic name to be serializable with the default system
@Override @Override
public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> ListOtherTables, final boolean createIfNotExist, public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> ListOtherTables, final boolean createIfNotExist,
final boolean createDrop, final int fieldId) throws Exception { final boolean createDrop, final int fieldId) throws Exception {
final String name = elem.getName(); final String name = AnnotationTools.getFieldName(elem);
String localName = name; String localName = name;
if (name.endsWith("s")) { if (name.endsWith("s")) {
localName = name.substring(0, name.length() - 1); localName = name.substring(0, name.length() - 1);
@ -230,13 +233,13 @@ public class AddOnSQLTableExternalLink implements SqlWrapperAddOn {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) { if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
otherTable.append("\t\t`id` bigint NOT NULL AUTO_INCREMENT,\n"); otherTable.append("\t\t`id` bigint NOT NULL AUTO_INCREMENT,\n");
otherTable.append("\t\t`deleted` tinyint(1) NOT NULL DEFAULT '0',\n"); otherTable.append("\t\t`deleted` tinyint(1) NOT NULL DEFAULT '0',\n");
otherTable.append("\t\t`create_date` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n"); otherTable.append("\t\t`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n");
otherTable.append("\t\t`modify_date` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n"); otherTable.append("\t\t`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n");
} else { } else {
otherTable.append("\t\t`id` INTEGER PRIMARY KEY AUTOINCREMENT,\n"); otherTable.append("\t\t`id` INTEGER PRIMARY KEY AUTOINCREMENT,\n");
otherTable.append("\t\t`deleted` INTEGER NOT NULL DEFAULT '0',\n"); otherTable.append("\t\t`deleted` INTEGER NOT NULL DEFAULT '0',\n");
otherTable.append("\t\t`create_date` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n"); otherTable.append("\t\t`createdAt` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
otherTable.append("\t\t`modify_date` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n"); otherTable.append("\t\t`updatedAt` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
} }
otherTable.append("\t\t`"); otherTable.append("\t\t`");
otherTable.append(tableName); otherTable.append(tableName);

View File

@ -0,0 +1,126 @@
package org.kar.archidata.sqlWrapper.addOn;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
import org.kar.archidata.sqlWrapper.StateLoad;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToOne;
public class AddOnManyToOne implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
/**
* Convert the list if external id in a string '-' separated
* @param ids List of value (null are removed)
* @return '-' string separated
*/
protected static String getStringOfIds(final List<Long> ids) {
final List<Long> tmp = new ArrayList<>(ids);
return tmp.stream().map(String::valueOf).collect(Collectors.joining("-"));
}
/**
* extract a list of "-" separated element from a SQL input data.
* @param rs Result Set of the BDD
* @param iii Id in the result set
* @return The list of Long value
* @throws SQLException if an error is generated in the sql request.
*/
protected static List<Long> getListOfIds(final ResultSet rs, final int iii) throws SQLException {
final String trackString = rs.getString(iii);
if (rs.wasNull()) {
return null;
}
final List<Long> out = new ArrayList<>();
final String[] elements = trackString.split("-");
for (final String elem : elements) {
final Long tmp = Long.parseLong(elem);
out.add(tmp);
}
return out;
}
@Override
public Class<?> getAnnotationClass() {
return ManyToOne.class;
}
@Override
public String getSQLFieldType(final Field elem) {
try {
return SqlWrapper.convertTypeInSQL(Long.class);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public boolean isCompatibleField(final Field elem) {
final ManyToOne decorators = elem.getDeclaredAnnotation(ManyToOne.class);
return decorators != null;
}
@Override
public int insertData(final PreparedStatement ps, final Object data, int iii) throws SQLException {
if (data == null) {
ps.setNull(iii++, Types.BIGINT);
} else {
@SuppressWarnings("unchecked")
String dataTmp = getStringOfIds((List<Long>) data);
ps.setString(iii++, dataTmp);
}
return iii++;
}
@Override
public boolean isExternal() {
// TODO Auto-generated method stub
return false;
}
@Override
public int generateQuerry(final String tableName, final Field elem, final StringBuilder querry, final String name, final List<StateLoad> autoClasify, QuerryOptions options) {
autoClasify.add(StateLoad.NORMAL);
querry.append(" ");
querry.append(tableName);
querry.append(".");
querry.append(name);
return 1;
}
@Override
public int fillFromQuerry(final ResultSet rs, final Field elem, final Object data, final int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
Long foreignKey = rs.getLong(count);
if (rs.wasNull()) {
return 0;
}
elem.set(data, foreignKey);
return 1;
}
@Override
public boolean canUpdate() {
return true;
}
// TODO : refacto this table to manage a generic table with dynamic name to be serializable with the default system
@Override
public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> ListOtherTables, final boolean createIfNotExist,
final boolean createDrop, final int fieldId) throws Exception {
SqlWrapper.createTablesSpecificType(tableName, elem, mainTableBuilder, ListOtherTables, createIfNotExist, createDrop, fieldId, Long.class);
}
}

View File

@ -9,7 +9,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.kar.archidata.annotation.addOn.SQLTableExternalLink; import org.kar.archidata.annotation.addOn.SQLTableExternalForeinKeyAsList;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper; import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn; import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
import org.kar.archidata.sqlWrapper.StateLoad; import org.kar.archidata.sqlWrapper.StateLoad;
@ -17,7 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn { public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnSQLTableExternalLink.class); static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
/** /**
* Convert the list if external id in a string '-' separated * Convert the list if external id in a string '-' separated
@ -55,15 +56,21 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
@Override @Override
public Class<?> getAnnotationClass() { public Class<?> getAnnotationClass() {
return SQLTableExternalLink.class; return SQLTableExternalForeinKeyAsList.class;
} }
public String getSQLFieldType(Field elem) { public String getSQLFieldType(Field elem) {
return "STRING"; try {
return SqlWrapper.convertTypeInSQL(String.class);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
} }
public boolean isCompatibleField(Field elem) { public boolean isCompatibleField(Field elem) {
SQLTableExternalLink decorators = elem.getDeclaredAnnotation(SQLTableExternalLink.class); SQLTableExternalForeinKeyAsList decorators = elem.getDeclaredAnnotation(SQLTableExternalForeinKeyAsList.class);
return decorators != null; return decorators != null;
} }
@ -85,7 +92,7 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
} }
@Override @Override
public int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List<StateLoad> autoClasify) { public int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List<StateLoad> autoClasify, QuerryOptions options) {
autoClasify.add(StateLoad.ARRAY); autoClasify.add(StateLoad.ARRAY);
querry.append(" "); querry.append(" ");
querry.append(tableName); querry.append(tableName);
@ -95,7 +102,7 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
} }
@Override @Override
public int fillFromQuerry(ResultSet rs, Field elem, Object data, int count) throws SQLException, IllegalArgumentException, IllegalAccessException { public int fillFromQuerry(ResultSet rs, Field elem, Object data, int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
List<Long> idList = getListOfIds(rs, count); List<Long> idList = getListOfIds(rs, count);
elem.set(data, idList); elem.set(data, idList);
return 1; return 1;

View File

@ -18,7 +18,7 @@ import org.kar.archidata.model.Data;
import org.kar.archidata.sqlWrapper.QuerryAnd; import org.kar.archidata.sqlWrapper.QuerryAnd;
import org.kar.archidata.sqlWrapper.QuerryCondition; import org.kar.archidata.sqlWrapper.QuerryCondition;
import org.kar.archidata.sqlWrapper.SqlWrapper; import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.addOn.AddOnSQLTableExternalLink; import org.kar.archidata.sqlWrapper.addOn.AddOnManyToMany;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -282,7 +282,7 @@ public class DataTools {
} }
// Fist step: retrieve all the Id of each parents:... // Fist step: retrieve all the Id of each parents:...
LOGGER.info("Find typeNode"); LOGGER.info("Find typeNode");
AddOnSQLTableExternalLink.addLink(clazz, id, "cover", data.id); AddOnManyToMany.addLink(clazz, id, "cover", data.id);
return Response.ok(SqlWrapper.get(clazz, id)).build(); return Response.ok(SqlWrapper.get(clazz, id)).build();
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Cat ann unexpected error ... "); System.out.println("Cat ann unexpected error ... ");