diff --git a/src/org/kar/archidata/annotation/AnnotationTools.java b/src/org/kar/archidata/annotation/AnnotationTools.java index 9de6323..0873e49 100644 --- a/src/org/kar/archidata/annotation/AnnotationTools.java +++ b/src/org/kar/archidata/annotation/AnnotationTools.java @@ -25,7 +25,7 @@ import jakarta.validation.constraints.Size; public class AnnotationTools { static final Logger LOGGER = LoggerFactory.getLogger(AnnotationTools.class); - + public static String getTableName(final Class clazz, final QueryOptions options) throws Exception { if (options != null) { final OverrideTableName data = options.get(OverrideTableName.class); @@ -35,7 +35,7 @@ public class AnnotationTools { } return AnnotationTools.getTableName(clazz); } - + public static String getTableName(final Class element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Table.class); if (annotation.length == 0) { @@ -51,7 +51,7 @@ public class AnnotationTools { } return tmp; } - + public static String getSchemedescription(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Schema.class); if (annotation.length == 0) { @@ -62,7 +62,7 @@ public class AnnotationTools { } return ((Schema) annotation[0]).description(); } - + public static String getComment(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataComment.class); if (annotation.length == 0) { @@ -73,7 +73,7 @@ public class AnnotationTools { } return ((DataComment) annotation[0]).value(); } - + public static String getDefault(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataDefault.class); if (annotation.length == 0) { @@ -84,7 +84,7 @@ public class AnnotationTools { } return ((DataDefault) annotation[0]).value(); } - + public static ManyToOne getManyToOne(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToOne.class); if (annotation.length == 0) { @@ -95,7 +95,7 @@ public class AnnotationTools { } return (ManyToOne) annotation[0]; } - + public static DataJson getDataJson(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataJson.class); if (annotation.length == 0) { @@ -106,7 +106,7 @@ public class AnnotationTools { } return (DataJson) annotation[0]; } - + public static Long getConstraintsMax(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Max.class); if (annotation.length == 0) { @@ -117,7 +117,7 @@ public class AnnotationTools { } return ((Max) annotation[0]).value(); } - + public static Long getConstraintsMin(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Min.class); if (annotation.length == 0) { @@ -128,7 +128,7 @@ public class AnnotationTools { } return ((Min) annotation[0]).value(); } - + public static int getLimitSize(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); if (annotation.length == 0) { @@ -140,7 +140,7 @@ public class AnnotationTools { final int length = ((Column) annotation[0]).length(); return length <= 0 ? 0 : length; } - + public static Size getConstraintsSize(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Size.class); if (annotation.length == 0) { @@ -151,7 +151,7 @@ public class AnnotationTools { } return (Size) annotation[0]; } - + public static String getConstraintsPattern(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Pattern.class); if (annotation.length == 0) { @@ -162,7 +162,7 @@ public class AnnotationTools { } return ((Pattern) annotation[0]).regexp(); } - + public static boolean isAnnotationGroup(final Field field, final Class annotationType) { try { final Annotation[] anns = field.getAnnotations(); @@ -185,7 +185,7 @@ public class AnnotationTools { } return false; } - + public static String getFieldName(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); if (annotation.length == 0) { @@ -200,7 +200,7 @@ public class AnnotationTools { } return name; } - + public static boolean getColumnNotNull(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); if (annotation.length == 0) { @@ -211,7 +211,7 @@ public class AnnotationTools { } return !((Column) annotation[0]).nullable(); } - + public static boolean getConstraintsNotNull(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(NotNull.class); if (annotation.length == 0) { @@ -222,7 +222,7 @@ public class AnnotationTools { } return true; } - + public static boolean isPrimaryKey(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Id.class); if (annotation.length == 0) { @@ -230,7 +230,7 @@ public class AnnotationTools { } return true; } - + public static boolean isUnique(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); if (annotation.length == 0) { @@ -241,7 +241,7 @@ public class AnnotationTools { } return ((Column) annotation[0]).unique(); } - + public static GenerationType getStrategy(final Field element) throws Exception { final Annotation[] annotation = element.getDeclaredAnnotationsByType(GeneratedValue.class); if (annotation.length == 0) { @@ -252,27 +252,27 @@ public class AnnotationTools { } return ((GeneratedValue) annotation[0]).strategy(); } - + public static boolean isDeletedField(final Field element) throws Exception { return element.getDeclaredAnnotationsByType(DataDeleted.class).length != 0; } - + public static boolean isCreatedAtField(final Field element) throws Exception { return element.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; } - + public static boolean isUpdateAtField(final Field element) throws Exception { return element.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; } - + public static boolean isdefaultNotRead(final Field element) throws Exception { return element.getDeclaredAnnotationsByType(DataNotRead.class).length != 0; } - + public static boolean isIdField(final Field element) throws Exception { return element.getDeclaredAnnotationsByType(Id.class).length != 0; } - + public static String getDeletedFieldName(final Class clazz) throws Exception { try { for (final Field elem : clazz.getFields()) { @@ -289,7 +289,7 @@ public class AnnotationTools { } return null; } - + public static String getUpdatedFieldName(final Class clazz) throws Exception { try { for (final Field elem : clazz.getFields()) { @@ -306,7 +306,7 @@ public class AnnotationTools { } return null; } - + public static Field getIdField(final Class clazz) { try { for (final Field field : clazz.getFields()) { @@ -323,15 +323,15 @@ public class AnnotationTools { } return null; } - + public static List getFieldsNames(final Class clazz) throws Exception { return getFieldsNamesFilter(clazz, false); } - + public static List getAllFieldsNames(final Class clazz) throws Exception { return getFieldsNamesFilter(clazz, true); } - + private static List getFieldsNamesFilter(final Class clazz, final boolean full) throws Exception { final List out = new ArrayList<>(); for (final Field field : clazz.getFields()) { @@ -346,11 +346,11 @@ public class AnnotationTools { } return out; } - + public static boolean isGenericField(final Field elem) throws Exception { return AnnotationTools.isPrimaryKey(elem) || AnnotationTools.isCreatedAtField(elem) || AnnotationTools.isUpdateAtField(elem) || AnnotationTools.isDeletedField(elem); } - + public static Field getFieldOfId(final Class clazz) throws Exception { for (final Field field : clazz.getFields()) { // static field is only for internal global declaration ==> remove it .. @@ -363,5 +363,18 @@ public class AnnotationTools { } return null; } - + + public static Field getFieldNamed(final Class clazz, final String name) throws Exception { + for (final Field field : clazz.getFields()) { + // static field is only for internal global declaration ==> remove it .. + if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { + continue; + } + if (AnnotationTools.getFieldName(field).equals(name)) { + return field; + } + } + return null; + } + } diff --git a/src/org/kar/archidata/dataAccess/DataAccess.java b/src/org/kar/archidata/dataAccess/DataAccess.java index 0b05447..1a4faeb 100644 --- a/src/org/kar/archidata/dataAccess/DataAccess.java +++ b/src/org/kar/archidata/dataAccess/DataAccess.java @@ -286,7 +286,7 @@ public class DataAccess { } iii.inc(); } - + protected static void setValueFromDb(final Class type, final Object data, final CountInOut count, final Field field, final ResultSet rs, final CountInOut countNotNull) throws Exception { if (type == Long.class) { final Long tmp = rs.getLong(count.value); @@ -445,6 +445,196 @@ public class DataAccess { } count.inc(); } + + // TODO: this function will replace the previous one !!! + protected static RetreiveFromDB createSetValueFromDbCallback(final int count, final Field field) throws Exception { + Class type = field.getType(); + if (type == Long.class) { + return (final ResultSet rs, Object obj) -> { + final Long tmp = rs.getLong(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == long.class) { + return (final ResultSet rs, Object obj) -> { + final Long tmp = rs.getLong(count); + if (rs.wasNull()) { + // field.set(data, null); + } else { + field.setLong(obj, tmp); + } + }; + } + if (type == Integer.class) { + return (final ResultSet rs, Object obj) -> { + final Integer tmp = rs.getInt(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == int.class) { + return (final ResultSet rs, Object obj) -> { + final Integer tmp = rs.getInt(count); + if (rs.wasNull()) { + // field.set(obj, null); + } else { + field.setInt(obj, tmp); + } + }; + } + if (type == Float.class) { + return (final ResultSet rs, Object obj) -> { + final Float tmp = rs.getFloat(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == float.class) { + return (final ResultSet rs, Object obj) -> { + final Float tmp = rs.getFloat(count); + if (rs.wasNull()) { + // field.set(obj, null); + } else { + field.setFloat(obj, tmp); + } + }; + } + if (type == Double.class) { + return (final ResultSet rs, Object obj) -> { + final Double tmp = rs.getDouble(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == double.class) { + return (final ResultSet rs, Object obj) -> { + final Double tmp = rs.getDouble(count); + if (rs.wasNull()) { + // field.set(obj, null); + } else { + field.setDouble(obj, tmp); + } + }; + } + if (type == Boolean.class) { + return (final ResultSet rs, Object obj) -> { + final Boolean tmp = rs.getBoolean(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == boolean.class) { + return (final ResultSet rs, Object obj) -> { + final Boolean tmp = rs.getBoolean(count); + if (rs.wasNull()) { + // field.set(obj, null); + } else { + field.setBoolean(obj, tmp); + } + }; + } + if (type == Timestamp.class) { + return (final ResultSet rs, Object obj) -> { + final Timestamp tmp = rs.getTimestamp(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type == Date.class) { + return (final ResultSet rs, Object obj) -> { + try { + final Timestamp tmp = rs.getTimestamp(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, Date.from(tmp.toInstant())); + } + } catch (final SQLException ex) { + final String tmp = rs.getString(count); + LOGGER.error("Fail to parse the SQL time !!! {}", tmp); + if (rs.wasNull()) { + field.set(obj, null); + } else { + final Date date = DateTools.parseDate(tmp); + LOGGER.error("Fail to parse the SQL time !!! {}", date); + field.set(obj, date); + } + } + }; + } + if (type == LocalDate.class) { + return (final ResultSet rs, Object obj) -> { + final java.sql.Date tmp = rs.getDate(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp.toLocalDate()); + } + }; + } + if (type == LocalTime.class) { + return (final ResultSet rs, Object obj) -> { + final java.sql.Time tmp = rs.getTime(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp.toLocalTime()); + } + }; + } + if (type == String.class) { + return (final ResultSet rs, Object obj) -> { + final String tmp = rs.getString(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + field.set(obj, tmp); + } + }; + } + if (type.isEnum()) { + return (final ResultSet rs, Object obj) -> { + final String tmp = rs.getString(count); + if (rs.wasNull()) { + field.set(obj, null); + } else { + boolean find = false; + final Object[] arr = type.getEnumConstants(); + for (final Object elem : arr) { + if (elem.toString().equals(tmp)) { + field.set(obj, elem); + find = true; + break; + } + } + if (!find) { + throw new DataAccessException("Enum value does not exist in the Model: '" + tmp + "'"); + } + } + }; + } + throw new DataAccessException("Unknown Field Type"); + + } public static boolean isAddOnField(final Field field) { return findAddOnforField(field) != null; @@ -1322,10 +1512,10 @@ public class DataAccess { - useful code to manage external query: List query(class clazz, ); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2"); */ - public static List querry(final Class clazz, String query, List parameters, final QueryOption... option) throws Exception { + public static List query(final Class clazz, String query, List parameters, final QueryOption... option) throws Exception { final QueryOptions options = new QueryOptions(option); final List lazyCall = new ArrayList<>(); - final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz); + // TODO ... final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz); final DBEntry entry = DBInterfaceOption.getAutoEntry(options); final List outs = new ArrayList<>(); // real add in the BDD: @@ -1336,32 +1526,27 @@ public class DataAccess { final PreparedStatement ps = entry.connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS); final CountInOut iii = new CountInOut(1); if (parameters != null) { - for (Object elem : parameters) + for (Object elem : parameters) { DataAccess.addElement(ps, elem, iii); + } iii.inc(); } - // execute the request final ResultSet rs = ps.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); List actionToRetreive = new ArrayList<>(); for (int jjj = 0; jjj < rsmd.getColumnCount(); jjj++) { - String name = rsmd.getColumnName(jjj); + String name = rsmd.getColumnName(jjj + 1); // find field name ... - + Field field = AnnotationTools.getFieldNamed(clazz, name); + if (field == null) { + throw new DataAccessException("Querry with unknown field: '" + name + "'"); + } // create the callback... - // TODO ... + RetreiveFromDB element = createSetValueFromDbCallback(jjj + 1, field); + actionToRetreive.add(element); } - /* - * - * - * j'en suis ici - * - * - * - */ - while (rs.next()) { count.value = 1; final CountInOut countNotNull = new CountInOut(0); diff --git a/test/src/test/kar/archidata/TestRawQuery.java b/test/src/test/kar/archidata/TestRawQuery.java new file mode 100644 index 0000000..8a308d1 --- /dev/null +++ b/test/src/test/kar/archidata/TestRawQuery.java @@ -0,0 +1,121 @@ +package test.kar.archidata; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kar.archidata.GlobalConfiguration; +import org.kar.archidata.dataAccess.DataAccess; +import org.kar.archidata.dataAccess.DataFactory; +import org.kar.archidata.db.DBEntry; +import org.kar.archidata.tools.ConfigBaseVariable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import test.kar.archidata.model.TypesTable; + +@ExtendWith(StepwiseExtension.class) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class TestRawQuery { + final static private Logger LOGGER = LoggerFactory.getLogger(TestTypes.class); + + @BeforeAll + public static void configureWebServer() throws Exception { + if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { + ConfigBaseVariable.dbType = "sqlite"; + ConfigBaseVariable.dbHost = "memory"; + // for test we need to connect all time the DB + ConfigBaseVariable.dbKeepConnected = "true"; + } + // Connect the dataBase... + final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); + entry.connect(); + } + + @AfterAll + public static void removeDataBase() throws IOException { + LOGGER.info("Remove the test db"); + DBEntry.closeAllForceMode(); + ConfigBaseVariable.clearAllValue(); + } + + @Order(1) + @Test + public void testCreateTable() throws Exception { + final List sqlCommand = DataFactory.createTable(TypesTable.class); + for (final String elem : sqlCommand) { + LOGGER.debug("request: '{}'", elem); + DataAccess.executeSimpleQuerry(elem); + } + } + + @Order(2) + @Test + public void testGet() throws Exception { + + final TypesTable test = new TypesTable(); + test.intData = 95; + test.floatData = 1.0F; + DataAccess.insert(test); + test.intData = 96; + test.floatData = 2.0F; + DataAccess.insert(test); + test.intData = 97; + test.floatData = 3.0F; + DataAccess.insert(test); + test.intData = 98; + test.floatData = 4.0F; + DataAccess.insert(test); + test.intData = 99; + test.floatData = 5.0F; + DataAccess.insert(test); + test.intData = 99; + test.floatData = 6.0F; + DataAccess.insert(test); + test.intData = 99; + test.floatData = 7.0F; + DataAccess.insert(test); + { + String querry = """ + SELECT * + FROM TypesTable + WHERE `intData` = ? + ORDER BY id DESC + """; + List parameters = List.of(Integer.valueOf(99)); + // Try to retrieve all the data: + final List retrieve = DataAccess.query(TypesTable.class, querry, parameters); + + Assertions.assertNotNull(retrieve); + Assertions.assertEquals(3, retrieve.size()); + Assertions.assertEquals(99, retrieve.get(0).intData); + Assertions.assertEquals(7.0F, retrieve.get(0).floatData); + Assertions.assertEquals(6.0F, retrieve.get(1).floatData); + Assertions.assertEquals(5.0F, retrieve.get(2).floatData); + } + { + + String querry = """ + SELECT DISTINCT intData + FROM TypesTable + WHERE `intData` = ? + ORDER BY id DESC + """; + List parameters = List.of(Integer.valueOf(99)); + // Try to retrieve all the data: + final List retrieve = DataAccess.query(TypesTable.class, querry, parameters); + + Assertions.assertNotNull(retrieve); + Assertions.assertEquals(1, retrieve.size()); + Assertions.assertEquals(99, retrieve.get(0).intData); + } + } + +} \ No newline at end of file