[FIX] better compatibility with @OneToMany

This commit is contained in:
Edouard DUPIN 2024-06-01 13:53:48 +02:00
parent c44b726cc1
commit c94f488747
4 changed files with 153 additions and 63 deletions

View File

@ -172,6 +172,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
} }
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0]; .getActualTypeArguments()[0];
// TODO: manage better the eager and lazy !!
if (objectClass == Long.class || objectClass == UUID.class) { if (objectClass == Long.class || objectClass == UUID.class) {
generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options); generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options);
} }

View File

@ -20,6 +20,7 @@ import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions; import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.exception.DataAccessException; import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -118,6 +119,64 @@ public class AddOnOneToMany implements DataAccessAddOn {
return false; return false;
} }
public void generateConcatQuery(
@NotNull final String tableName,
@NotNull final String primaryKey,
@NotNull final Field field,
@NotNull final StringBuilder querySelect,
@NotNull final StringBuilder query,
@NotNull final String name,
@NotNull final CountInOut count,
final QueryOptions options,
final Class<?> targetEntity,
final String mappedBy) throws Exception {
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
final String remoteTableName = AnnotationTools.getTableName(targetEntity);
final String remoteTablePrimaryKeyName = AnnotationTools
.getFieldName(AnnotationTools.getPrimaryKeyField(targetEntity));
final String tmpRemoteVariable = "tmp_" + Integer.toString(count.value);
final String remoteDeletedFieldName = AnnotationTools.getDeletedFieldName(targetEntity);
querySelect.append(" (SELECT GROUP_CONCAT(");
querySelect.append(tmpRemoteVariable);
querySelect.append(".");
querySelect.append(remoteTablePrimaryKeyName);
querySelect.append(" ");
if ("sqlite".equals(ConfigBaseVariable.getDBType())) {
querySelect.append(", ");
} else {
querySelect.append("SEPARATOR ");
}
querySelect.append("'");
if (objectClass == Long.class) {
querySelect.append(SEPARATOR_LONG);
}
querySelect.append("') FROM ");
querySelect.append(remoteTableName);
querySelect.append(" ");
querySelect.append(tmpRemoteVariable);
querySelect.append(" WHERE ");
if (remoteDeletedFieldName != null) {
querySelect.append(tmpRemoteVariable);
querySelect.append(".");
querySelect.append(remoteDeletedFieldName);
querySelect.append(" = false");
querySelect.append(" AND ");
}
querySelect.append(tableName);
querySelect.append(".");
querySelect.append(primaryKey);
querySelect.append(" = ");
querySelect.append(tmpRemoteVariable);
querySelect.append(".");
querySelect.append(mappedBy);
querySelect.append(" ");
querySelect.append(") AS ");
querySelect.append(name);
querySelect.append(" ");
}
@Override @Override
public void generateQuery( public void generateQuery(
@NotNull final String tableName, @NotNull final String tableName,
@ -127,10 +186,26 @@ public class AddOnOneToMany implements DataAccessAddOn {
@NotNull final StringBuilder query, @NotNull final StringBuilder query,
@NotNull final String name, @NotNull final String name,
@NotNull final CountInOut count, @NotNull final CountInOut count,
final QueryOptions options) { final QueryOptions options) throws Exception {
if (field.getType() != List.class) { if (field.getType() != List.class) {
return; return;
} }
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
if (decorators == null) {
return;
}
// TODO: manage better the eager and lazy !!
if (objectClass == Long.class || objectClass == UUID.class) {
generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options,
decorators.targetEntity(), decorators.mappedBy());
return;
}
if (objectClass == decorators.targetEntity()) {
if (decorators.fetch() == FetchType.EAGER) {
throw new DataAccessException("EAGER is not supported for list of element...");
} else {
// Force a copy of the primaryKey to permit the async retrieve of the data // Force a copy of the primaryKey to permit the async retrieve of the data
querySelect.append(" "); querySelect.append(" ");
querySelect.append(tableName); querySelect.append(tableName);
@ -139,6 +214,8 @@ public class AddOnOneToMany implements DataAccessAddOn {
querySelect.append(" AS tmp_"); querySelect.append(" AS tmp_");
querySelect.append(Integer.toString(count.value)); querySelect.append(Integer.toString(count.value));
} }
}
}
@Override @Override
public void fillFromQuery( public void fillFromQuery(
@ -152,6 +229,24 @@ public class AddOnOneToMany implements DataAccessAddOn {
LOGGER.error("Can not OneToMany with other than List Model: {}", field.getType().getCanonicalName()); LOGGER.error("Can not OneToMany with other than List Model: {}", field.getType().getCanonicalName());
return; return;
} }
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
if (decorators == null) {
return;
}
if (objectClass == Long.class) {
final List<Long> idList = DataAccess.getListOfIds(rs, count.value, SEPARATOR_LONG);
field.set(data, idList);
count.inc();
return;
} else if (objectClass == UUID.class) {
final List<UUID> idList = DataAccess.getListOfRawUUIDs(rs, count.value);
field.set(data, idList);
count.inc();
return;
}
if (objectClass == decorators.targetEntity()) {
Long parentIdTmp = null; Long parentIdTmp = null;
UUID parendUuidTmp = null; UUID parendUuidTmp = null;
@ -166,15 +261,8 @@ public class AddOnOneToMany implements DataAccessAddOn {
} }
final Long parentId = parentIdTmp; final Long parentId = parentIdTmp;
final UUID parendUuid = parendUuidTmp; final UUID parendUuid = parendUuidTmp;
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
if (decorators == null) {
return;
}
final String mappingKey = decorators.mappedBy(); final String mappingKey = decorators.mappedBy();
// We get the parent ID ... ==> need to request the list of elements // We get the parent ID ... ==> need to request the list of elements
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
if (objectClass == Long.class) { if (objectClass == Long.class) {
LOGGER.error("Need to retreive all primary key of all elements"); LOGGER.error("Need to retreive all primary key of all elements");
//field.set(data, idList); //field.set(data, idList);
@ -213,6 +301,7 @@ public class AddOnOneToMany implements DataAccessAddOn {
} }
} }
} }
}
// TODO : refacto this table to manage a generic table with dynamic name to be serialize with the default system // TODO : refacto this table to manage a generic table with dynamic name to be serialize with the default system
@Override @Override

View File

@ -153,13 +153,13 @@ public class TestOneToMany {
root.otherData = "plouf"; root.otherData = "plouf";
final TypeOneToManyUUIDRoot insertedRoot = DataAccess.insert(root); final TypeOneToManyUUIDRoot insertedRoot = DataAccess.insert(root);
Assertions.assertEquals(insertedRoot.otherData, root.otherData); Assertions.assertEquals(insertedRoot.otherData, root.otherData);
Assertions.assertNotNull(insertedRoot.remoteIds); Assertions.assertNull(insertedRoot.remoteIds);
final TypeOneToManyUUIDRoot root2 = new TypeOneToManyUUIDRoot(); final TypeOneToManyUUIDRoot root2 = new TypeOneToManyUUIDRoot();
root2.otherData = "plouf 2"; root2.otherData = "plouf 2";
final TypeOneToManyUUIDRoot insertedRoot2 = DataAccess.insert(root2); final TypeOneToManyUUIDRoot insertedRoot2 = DataAccess.insert(root2);
Assertions.assertEquals(insertedRoot2.otherData, root2.otherData); Assertions.assertEquals(insertedRoot2.otherData, root2.otherData);
Assertions.assertNotNull(insertedRoot2.remoteIds); Assertions.assertNull(insertedRoot2.remoteIds);
// Create Some Remotes // Create Some Remotes
@ -188,14 +188,14 @@ public class TestOneToMany {
final TypeOneToManyUUIDRoot retreiveRoot1 = DataAccess.get(TypeOneToManyUUIDRoot.class, insertedRoot.uuid); final TypeOneToManyUUIDRoot retreiveRoot1 = DataAccess.get(TypeOneToManyUUIDRoot.class, insertedRoot.uuid);
Assertions.assertEquals(retreiveRoot1.otherData, insertedRoot.otherData); Assertions.assertEquals(retreiveRoot1.otherData, insertedRoot.otherData);
Assertions.assertNull(retreiveRoot1.remoteIds); Assertions.assertNotNull(retreiveRoot1.remoteIds);
Assertions.assertEquals(2, retreiveRoot1.remoteIds.size()); Assertions.assertEquals(2, retreiveRoot1.remoteIds.size());
Assertions.assertEquals(insertedRemote10.uuid, retreiveRoot1.remoteIds.get(0)); Assertions.assertEquals(insertedRemote10.uuid, retreiveRoot1.remoteIds.get(0));
Assertions.assertEquals(insertedRemote11.uuid, retreiveRoot1.remoteIds.get(1)); Assertions.assertEquals(insertedRemote11.uuid, retreiveRoot1.remoteIds.get(1));
final TypeOneToManyUUIDRoot retreiveRoot2 = DataAccess.get(TypeOneToManyUUIDRoot.class, insertedRoot2.uuid); final TypeOneToManyUUIDRoot retreiveRoot2 = DataAccess.get(TypeOneToManyUUIDRoot.class, insertedRoot2.uuid);
Assertions.assertEquals(retreiveRoot2.otherData, insertedRoot2.otherData); Assertions.assertEquals(retreiveRoot2.otherData, insertedRoot2.otherData);
Assertions.assertNull(retreiveRoot2.remoteIds); Assertions.assertNotNull(retreiveRoot2.remoteIds);
Assertions.assertEquals(1, retreiveRoot2.remoteIds.size()); Assertions.assertEquals(1, retreiveRoot2.remoteIds.size());
Assertions.assertEquals(insertedRemote20.uuid, retreiveRoot2.remoteIds.get(0)); Assertions.assertEquals(insertedRemote20.uuid, retreiveRoot2.remoteIds.get(0));
@ -204,7 +204,7 @@ public class TestOneToMany {
final TypeOneToManyUUIDRootExpand retreiveRootExpand1 = DataAccess.get(TypeOneToManyUUIDRootExpand.class, final TypeOneToManyUUIDRootExpand retreiveRootExpand1 = DataAccess.get(TypeOneToManyUUIDRootExpand.class,
insertedRoot.uuid); insertedRoot.uuid);
Assertions.assertEquals(retreiveRootExpand1.otherData, insertedRoot.otherData); Assertions.assertEquals(retreiveRootExpand1.otherData, insertedRoot.otherData);
Assertions.assertNull(retreiveRootExpand1.remotes); Assertions.assertNotNull(retreiveRootExpand1.remotes);
Assertions.assertEquals(2, retreiveRootExpand1.remotes.size()); Assertions.assertEquals(2, retreiveRootExpand1.remotes.size());
Assertions.assertEquals(insertedRemote10.uuid, retreiveRootExpand1.remotes.get(0).uuid); Assertions.assertEquals(insertedRemote10.uuid, retreiveRootExpand1.remotes.get(0).uuid);
Assertions.assertEquals(insertedRemote10.rootUuid, retreiveRootExpand1.remotes.get(0).rootUuid); Assertions.assertEquals(insertedRemote10.rootUuid, retreiveRootExpand1.remotes.get(0).rootUuid);
@ -216,7 +216,7 @@ public class TestOneToMany {
final TypeOneToManyUUIDRootExpand retreiveRootExpand2 = DataAccess.get(TypeOneToManyUUIDRootExpand.class, final TypeOneToManyUUIDRootExpand retreiveRootExpand2 = DataAccess.get(TypeOneToManyUUIDRootExpand.class,
insertedRoot2.uuid); insertedRoot2.uuid);
Assertions.assertEquals(retreiveRootExpand2.otherData, insertedRoot2.otherData); Assertions.assertEquals(retreiveRootExpand2.otherData, insertedRoot2.otherData);
Assertions.assertNull(retreiveRootExpand2.remotes); Assertions.assertNotNull(retreiveRootExpand2.remotes);
Assertions.assertEquals(1, retreiveRootExpand2.remotes.size()); Assertions.assertEquals(1, retreiveRootExpand2.remotes.size());
Assertions.assertEquals(insertedRemote20.uuid, retreiveRootExpand2.remotes.get(0).uuid); Assertions.assertEquals(insertedRemote20.uuid, retreiveRootExpand2.remotes.get(0).uuid);
Assertions.assertEquals(insertedRemote20.rootUuid, retreiveRootExpand2.remotes.get(0).rootUuid); Assertions.assertEquals(insertedRemote20.rootUuid, retreiveRootExpand2.remotes.get(0).rootUuid);

View File

@ -12,7 +12,7 @@ public class TypeOneToManyUUIDRoot extends UUIDGenericData {
public String otherData; public String otherData;
@OneToMany(targetEntity = TypeOneToManyUUIDRemote.class, mappedBy = "rootId") @OneToMany(targetEntity = TypeOneToManyUUIDRemote.class, mappedBy = "rootUuid")
@Column(nullable = false) @Column(nullable = false)
public List<UUID> remoteIds; public List<UUID> remoteIds;
} }