From be8a5c713aa46b3edeb396a1343b9ab3862c98b7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 17 Feb 2025 00:16:11 +0100 Subject: [PATCH] [FIX] ObjectId manyToOne and OneToMany --- .../dataAccess/addOnSQL/AddOnManyToMany.java | 51 +++++++++++++++---- .../dataAccess/addOnSQL/AddOnManyToOne.java | 43 ++++++++++++++-- .../dataAccess/addOnSQL/AddOnOneToMany.java | 41 ++++++++++++--- 3 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToMany.java b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToMany.java index 48235b4..0084c00 100644 --- a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToMany.java +++ b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToMany.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.kar.archidata.dataAccess.CountInOut; @@ -72,7 +73,7 @@ public class AddOnManyToMany implements DataAccessAddOn { } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; - if (objectClass == Long.class || objectClass == UUID.class) { + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { return true; } final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); @@ -135,7 +136,11 @@ public class AddOnManyToMany implements DataAccessAddOn { querySelect.append("'"); if (objectClass == Long.class) { querySelect.append(SEPARATOR_LONG); - } else if (objectClass == UUID.class) {} else { + } else if (objectClass == UUID.class) { + // ??? + } else if (objectClass == ObjectId.class) { + // ??? + } else { final Class foreignKeyType = AnnotationTools.getPrimaryKeyField(objectClass).getType(); if (foreignKeyType == Long.class) { querySelect.append(SEPARATOR_LONG); @@ -193,7 +198,7 @@ public class AddOnManyToMany implements DataAccessAddOn { final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; // TODO: manage better the eager and lazy !! - if (objectClass == Long.class || objectClass == UUID.class) { + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options); } final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); @@ -234,6 +239,11 @@ public class AddOnManyToMany implements DataAccessAddOn { field.set(data, idList); count.inc(); return; + } else if (objectClass == ObjectId.class) { + final List idList = ioDb.getListOfRawOIDs(rs, count.value); + field.set(data, idList); + count.inc(); + return; } final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); if (decorators == null) { @@ -285,6 +295,27 @@ public class AddOnManyToMany implements DataAccessAddOn { }; lazyCall.add(lambda); } + } else if (foreignKeyType == ObjectId.class) { + final List idList = ioDb.getListOfRawOIDs(rs, count.value); + // field.set(data, idList); + count.inc(); + if (idList != null && idList.size() > 0) { + final FieldName idField = AnnotationTools.getFieldName(AnnotationTools.getIdField(objectClass), + options); + // In the lazy mode, the request is done in asynchronous mode, they will be done after... + final LazyGetter lambda = () -> { + final List childs = new ArrayList<>(idList); + // TODO: update to have get with abstract types .... + @SuppressWarnings("unchecked") + final Object foreignData = ioDb.getsWhere(decorators.targetEntity(), + new Condition(new QueryInList<>(idField.inTable(), childs))); + if (foreignData == null) { + return; + } + field.set(data, foreignData); + }; + lazyCall.add(lambda); + } } } } @@ -309,9 +340,10 @@ public class AddOnManyToMany implements DataAccessAddOn { } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; - if (objectClass != Long.class && objectClass != UUID.class) { - throw new DataAccessException("Can not ManyToMany with other than List or List Model: List<" - + objectClass.getCanonicalName() + ">"); + if (objectClass != Long.class && objectClass != UUID.class && objectClass != ObjectId.class) { + throw new DataAccessException( + "Can not ManyToMany with other than List or List or List Model: List<" + + objectClass.getCanonicalName() + ">"); } final FieldName columnName = AnnotationTools.getFieldName(field, options); final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); @@ -348,9 +380,10 @@ public class AddOnManyToMany implements DataAccessAddOn { } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; - if (objectClass != Long.class && objectClass != UUID.class) { - throw new DataAccessException("Can not ManyToMany with other than List or List Model: List<" - + objectClass.getCanonicalName() + ">"); + if (objectClass != Long.class && objectClass != UUID.class && objectClass != ObjectId.class) { + throw new DataAccessException( + "Can not ManyToMany with other than List or List or List Model: List<" + + objectClass.getCanonicalName() + ">"); } final FieldName columnName = AnnotationTools.getFieldName(field, options); final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); diff --git a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToOne.java b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToOne.java index d6d81d6..f3656c1 100644 --- a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToOne.java +++ b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnManyToOne.java @@ -7,6 +7,7 @@ import java.sql.Types; import java.util.List; import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.kar.archidata.dataAccess.CountInOut; @@ -66,6 +67,8 @@ public class AddOnManyToOne implements DataAccessAddOn { ps.setNull(iii.value, Types.VARCHAR); } else if (field.getType() == UUID.class) { ps.setNull(iii.value, Types.BINARY); + } else if (field.getType() == ObjectId.class) { + ps.setNull(iii.value, Types.BINARY); } } else if (field.getType() == Long.class) { final Long dataTyped = (Long) data; @@ -84,6 +87,11 @@ public class AddOnManyToOne implements DataAccessAddOn { LOGGER.info("Generate UUTD for DB: {}", dataTyped); final byte[] dataByte = UuidUtils.asBytes(dataTyped); ps.setBytes(iii.value, dataByte); + } else if (field.getType() == ObjectId.class) { + final ObjectId dataTyped = (ObjectId) data; + LOGGER.info("Generate ObjectId for DB: {}", dataTyped); + final byte[] dataByte = dataTyped.toByteArray(); + ps.setBytes(iii.value, dataByte); } else { final Field idField = AnnotationTools.getFieldOfId(field.getType()); final Object uid = idField.get(data); @@ -101,7 +109,8 @@ public class AddOnManyToOne implements DataAccessAddOn { @Override public boolean canInsert(final Field field) { if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class - || field.getType() == String.class || field.getType() == UUID.class) { + || field.getType() == String.class || field.getType() == UUID.class + || field.getType() == ObjectId.class) { return true; } final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); @@ -120,7 +129,7 @@ public class AddOnManyToOne implements DataAccessAddOn { public boolean canRetrieve(final Field field) { final Class classType = field.getType(); if (classType == Long.class || classType == Integer.class || classType == Short.class - || classType == String.class || classType == UUID.class) { + || classType == String.class || classType == UUID.class || classType == ObjectId.class) { return true; } final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); @@ -141,7 +150,8 @@ public class AddOnManyToOne implements DataAccessAddOn { @NotNull final CountInOut count, final QueryOptions options) throws Exception { if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class - || field.getType() == String.class || field.getType() == UUID.class) { + || field.getType() == String.class || field.getType() == UUID.class + || field.getType() == ObjectId.class) { querySelect.append(" "); querySelect.append(tableName); querySelect.append("."); @@ -230,6 +240,15 @@ public class AddOnManyToOne implements DataAccessAddOn { } return; } + if (field.getType() == ObjectId.class) { + final byte[] tmp = rs.getBytes(count.value); + count.inc(); + if (!rs.wasNull()) { + final ObjectId foreignKey = new ObjectId(tmp); + field.set(data, foreignKey); + } + return; + } final Class objectClass = field.getType(); final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); if (decorators == null) { @@ -279,6 +298,22 @@ public class AddOnManyToOne implements DataAccessAddOn { }; lazyCall.add(lambda); } + } else if (remotePrimaryKeyType == ObjectId.class) { + // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... + final ObjectId foreignKey = ioDb.getListOfRawOID(rs, count.value); + count.inc(); + if (foreignKey != null) { + // In the lazy mode, the request is done in asynchronous mode, they will be done after... + final LazyGetter lambda = () -> { + // TODO: update to have get with abstract types .... + final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); + if (foreignData == null) { + return; + } + field.set(data, foreignData); + }; + lazyCall.add(lambda); + } } } } @@ -298,7 +333,7 @@ public class AddOnManyToOne implements DataAccessAddOn { final QueryOptions options) throws Exception { final Class classType = field.getType(); if (classType == Long.class || classType == Integer.class || classType == Short.class - || classType == String.class || classType == UUID.class) { + || classType == String.class || classType == UUID.class || classType == ObjectId.class) { DataFactory.createTablesSpecificType(tableName, primaryField, field, mainTableBuilder, preActionList, postActionList, createIfNotExist, createDrop, fieldId, classType, options); } else { diff --git a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnOneToMany.java b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnOneToMany.java index 25c509d..52b8f0f 100644 --- a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnOneToMany.java +++ b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnOneToMany.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.kar.archidata.dataAccess.CountInOut; @@ -110,7 +111,7 @@ public class AddOnOneToMany implements DataAccessAddOn { } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; - if (objectClass == Long.class || objectClass == UUID.class) { + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { return true; } final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class); @@ -201,7 +202,7 @@ public class AddOnOneToMany implements DataAccessAddOn { return; } // TODO: manage better the eager and lazy !! - if (objectClass == Long.class || objectClass == UUID.class) { + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options, decorators.targetEntity(), decorators.mappedBy()); return; @@ -250,22 +251,35 @@ public class AddOnOneToMany implements DataAccessAddOn { field.set(data, idList); count.inc(); return; + } else if (objectClass == ObjectId.class) { + final List idList = ioDb.getListOfRawOIDs(rs, count.value); + field.set(data, idList); + count.inc(); + return; } if (objectClass == decorators.targetEntity()) { - Long parentIdTmp = null; UUID parendUuidTmp = null; + ObjectId parendOidTmp = null; try { final String modelData = rs.getString(count.value); parentIdTmp = Long.valueOf(modelData); count.inc(); } catch (final NumberFormatException ex) { - final List idList = ioDb.getListOfRawUUIDs(rs, count.value); - parendUuidTmp = idList.get(0); - count.inc(); + try { + final List idList = ioDb.getListOfRawUUIDs(rs, count.value); + parendUuidTmp = idList.get(0); + count.inc(); + } catch (final NumberFormatException ex2) { + // TODO : How to manage ObjectId ==> I am not sure it works well... + final List idList = ioDb.getListOfRawOIDs(rs, count.value); + parendOidTmp = idList.get(0); + count.inc(); + } } final Long parentId = parentIdTmp; final UUID parendUuid = parendUuidTmp; + final ObjectId parendOid = parendOidTmp; final String mappingKey = decorators.mappedBy(); // We get the parent ID ... ==> need to request the list of elements if (objectClass == Long.class) { @@ -276,6 +290,10 @@ public class AddOnOneToMany implements DataAccessAddOn { LOGGER.error("Need to retreive all primary key of all elements"); //field.set(data, idList); return; + } else if (objectClass == ObjectId.class) { + LOGGER.error("Need to retreive all primary key of all elements"); + //field.set(data, idList); + return; } if (objectClass == decorators.targetEntity()) { if (decorators.fetch() == FetchType.EAGER) { @@ -303,6 +321,17 @@ public class AddOnOneToMany implements DataAccessAddOn { field.set(data, foreignData); }; lazyCall.add(lambda); + } else if (parendOid != null) { + final LazyGetter lambda = () -> { + @SuppressWarnings("unchecked") + final Object foreignData = ioDb.getsWhere(decorators.targetEntity(), + new Condition(new QueryCondition(mappingKey, "=", parendOid))); + if (foreignData == null) { + return; + } + field.set(data, foreignData); + }; + lazyCall.add(lambda); } } }