[FIX] better compatibility with @OneToMany
This commit is contained in:
parent
c44b726cc1
commit
c94f488747
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,17 +186,35 @@ 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;
|
||||||
}
|
}
|
||||||
// Force a copy of the primaryKey to permit the async retrieve of the data
|
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
|
||||||
querySelect.append(" ");
|
.getActualTypeArguments()[0];
|
||||||
querySelect.append(tableName);
|
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
|
||||||
querySelect.append(".");
|
if (decorators == null) {
|
||||||
querySelect.append(primaryKey);
|
return;
|
||||||
querySelect.append(" AS tmp_");
|
}
|
||||||
querySelect.append(Integer.toString(count.value));
|
// 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
|
||||||
|
querySelect.append(" ");
|
||||||
|
querySelect.append(tableName);
|
||||||
|
querySelect.append(".");
|
||||||
|
querySelect.append(primaryKey);
|
||||||
|
querySelect.append(" AS tmp_");
|
||||||
|
querySelect.append(Integer.toString(count.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -152,64 +229,76 @@ 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())
|
||||||
Long parentIdTmp = null;
|
.getActualTypeArguments()[0];
|
||||||
UUID parendUuidTmp = null;
|
|
||||||
try {
|
|
||||||
final String modelData = rs.getString(count.value);
|
|
||||||
parentIdTmp = Long.valueOf(modelData);
|
|
||||||
count.inc();
|
|
||||||
} catch (final NumberFormatException ex) {
|
|
||||||
final List<UUID> idList = DataAccess.getListOfRawUUIDs(rs, count.value);
|
|
||||||
parendUuidTmp = idList.get(0);
|
|
||||||
count.inc();
|
|
||||||
}
|
|
||||||
final Long parentId = parentIdTmp;
|
|
||||||
final UUID parendUuid = parendUuidTmp;
|
|
||||||
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
|
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
|
||||||
if (decorators == null) {
|
if (decorators == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String mappingKey = decorators.mappedBy();
|
|
||||||
// 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");
|
final List<Long> idList = DataAccess.getListOfIds(rs, count.value, SEPARATOR_LONG);
|
||||||
//field.set(data, idList);
|
field.set(data, idList);
|
||||||
|
count.inc();
|
||||||
return;
|
return;
|
||||||
} else if (objectClass == UUID.class) {
|
} else if (objectClass == UUID.class) {
|
||||||
LOGGER.error("Need to retreive all primary key of all elements");
|
final List<UUID> idList = DataAccess.getListOfRawUUIDs(rs, count.value);
|
||||||
//field.set(data, idList);
|
field.set(data, idList);
|
||||||
|
count.inc();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (objectClass == decorators.targetEntity()) {
|
if (objectClass == decorators.targetEntity()) {
|
||||||
if (decorators.fetch() == FetchType.EAGER) {
|
|
||||||
throw new DataAccessException("EAGER is not supported for list of element...");
|
Long parentIdTmp = null;
|
||||||
} else if (parentId != null) {
|
UUID parendUuidTmp = null;
|
||||||
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
|
try {
|
||||||
final LazyGetter lambda = () -> {
|
final String modelData = rs.getString(count.value);
|
||||||
@SuppressWarnings("unchecked")
|
parentIdTmp = Long.valueOf(modelData);
|
||||||
final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(),
|
count.inc();
|
||||||
new Condition(new QueryCondition(mappingKey, "=", parentId)));
|
} catch (final NumberFormatException ex) {
|
||||||
if (foreignData == null) {
|
final List<UUID> idList = DataAccess.getListOfRawUUIDs(rs, count.value);
|
||||||
return;
|
parendUuidTmp = idList.get(0);
|
||||||
}
|
count.inc();
|
||||||
field.set(data, foreignData);
|
}
|
||||||
};
|
final Long parentId = parentIdTmp;
|
||||||
lazyCall.add(lambda);
|
final UUID parendUuid = parendUuidTmp;
|
||||||
} else if (parendUuid != null) {
|
final String mappingKey = decorators.mappedBy();
|
||||||
final LazyGetter lambda = () -> {
|
// We get the parent ID ... ==> need to request the list of elements
|
||||||
@SuppressWarnings("unchecked")
|
if (objectClass == Long.class) {
|
||||||
final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(),
|
LOGGER.error("Need to retreive all primary key of all elements");
|
||||||
new Condition(new QueryCondition(mappingKey, "=", parendUuid)));
|
//field.set(data, idList);
|
||||||
if (foreignData == null) {
|
return;
|
||||||
return;
|
} else if (objectClass == UUID.class) {
|
||||||
}
|
LOGGER.error("Need to retreive all primary key of all elements");
|
||||||
field.set(data, foreignData);
|
//field.set(data, idList);
|
||||||
};
|
return;
|
||||||
lazyCall.add(lambda);
|
}
|
||||||
|
if (objectClass == decorators.targetEntity()) {
|
||||||
|
if (decorators.fetch() == FetchType.EAGER) {
|
||||||
|
throw new DataAccessException("EAGER is not supported for list of element...");
|
||||||
|
} else if (parentId != null) {
|
||||||
|
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
|
||||||
|
final LazyGetter lambda = () -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(),
|
||||||
|
new Condition(new QueryCondition(mappingKey, "=", parentId)));
|
||||||
|
if (foreignData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.set(data, foreignData);
|
||||||
|
};
|
||||||
|
lazyCall.add(lambda);
|
||||||
|
} else if (parendUuid != null) {
|
||||||
|
final LazyGetter lambda = () -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(),
|
||||||
|
new Condition(new QueryCondition(mappingKey, "=", parendUuid)));
|
||||||
|
if (foreignData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.set(data, foreignData);
|
||||||
|
};
|
||||||
|
lazyCall.add(lambda);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user