Skip managed tables in M2M updates

This commit is contained in:
Roland Praml
2022-08-09 11:46:08 +02:00
parent ad6579d360
commit a5d25626f0
7 changed files with 42 additions and 13 deletions
@@ -1934,13 +1934,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return owner.descriptor(otherType);
}
/**
* Returns true, if the table is managed (i.e. an existing m2m relation).
*/
public boolean isTableManaged(String tableName) {
return owner.isTableManaged(tableName);
}
/**
* Return the order column property.
*/
@@ -89,6 +89,8 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private final String serverName;
private final List<BeanDescriptor<?>> elementDescriptors = new ArrayList<>();
private final Map<String, BeanTable> beanTableMap = new HashMap<>();
private final Set<String> managedTables = new HashSet<>();
private final Map<String, BeanDescriptor<?>> descMap = new HashMap<>();
private final Map<String, BeanDescriptor<?>> descQueueMap = new HashMap<>();
private final Map<String, BeanManager<?>> beanManagerMap = new HashMap<>();
@@ -422,8 +424,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
@Override
public boolean isTableManaged(String tableName) {
return tableToDescMap.get(tableName.toLowerCase()) != null
|| tableToViewDescMap.get(tableName.toLowerCase()) != null;
return managedTables.contains(tableName);
}
/**
@@ -691,6 +692,9 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
BeanTable beanTable = createBeanTable(info);
beanTableMap.put(beanTable.getBeanType().getName(), beanTable);
if (beanTable.getBaseTable() != null) {
managedTables.add(beanTable.getBaseTable());
}
}
// register non-id embedded beans (after bean tables are created)
for (DeployBeanInfo<?> info : embeddedBeans) {
@@ -36,6 +36,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
* Join for manyToMany intersection table.
*/
private final TableJoin intersectionJoin;
private final boolean tableManaged;
private final String intersectionPublishTable;
private final String intersectionDraftTable;
private final boolean orphanRemoval;
@@ -98,9 +100,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
this.fetchOrderBy = deploy.getFetchOrderBy();
this.intersectionJoin = deploy.createIntersectionTableJoin();
if (intersectionJoin != null) {
this.tableManaged = deploy.isTableManaged();
this.intersectionPublishTable = intersectionJoin.getTable();
this.intersectionDraftTable = deploy.getIntersectionDraftTable();
} else {
this.tableManaged = false;
this.intersectionPublishTable = null;
this.intersectionDraftTable = null;
}
@@ -912,11 +916,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
// Note ManyToMany always included as we always 'save'
// the relationship via insert/delete of intersection table
// REMOVALS means including PrivateOwned relationships
return cascadeInfo.isSave() || hasJoinTable() || ModifyListenMode.REMOVALS == modifyListenMode;
return cascadeInfo.isSave() || (hasJoinTable() && !tableManaged) || ModifyListenMode.REMOVALS == modifyListenMode;
}
public boolean isIncludeCascadeDelete() {
return cascadeInfo.isDelete() || hasJoinTable() || ModifyListenMode.REMOVALS == modifyListenMode;
return cascadeInfo.isDelete() || (hasJoinTable() && !tableManaged) || ModifyListenMode.REMOVALS == modifyListenMode;
}
boolean isCascadeDeleteEscalate() {
@@ -1050,7 +1054,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
public boolean createJoinTable() {
if (hasJoinTable() && mappedBy() == null) {
// only create on other 'owning' side
return !descriptor.isTableManaged(intersectionJoin.getTable());
return !tableManaged;
} else {
return false;
}
@@ -63,6 +63,13 @@ public class DeployBeanDescriptor<T> implements DeployBeanDescriptorMeta {
private static final Map<String, SpiRawSql> EMPTY_RAW_MAP = new HashMap<>();
/**
* Returns true, if the table is managed (i.e. an existing m2m relation).
*/
public boolean isTableManaged(String tableName) {
return manager.isTableManaged(tableName);
}
private static class PropOrder implements Comparator<DeployBeanProperty> {
@Override
@@ -113,6 +113,10 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
}
}
public boolean isTableManaged() {
return intersectionJoin != null && desc.isTableManaged(intersectionJoin.getTable());
}
/**
* Create the immutable version of the inverse join.
*/
@@ -16,7 +16,7 @@ public class MnyNode {
String name;
@ManyToMany
@ManyToMany(cascade = CascadeType.REFRESH)
@JoinTable(name = "mny_edge",
joinColumns = @JoinColumn(name = "from_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "to_id", referencedColumnName = "id"))
@@ -18,6 +18,23 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class TestM2MWithWhere extends BaseTestCase {
@Test
public void testModify() throws Exception {
createTestData();
MnyNode node = DB.find(MnyNode.class, 1);
node.setName("fooBarBaz");
MnyNode removed = node.getAllRelations().remove(0);
LoggedSql.start();
DB.save(node);
List<String> sql = LoggedSql.stop();
sql.forEach(System.out::println);
node.getAllRelations().add(removed);
LoggedSql.start();
DB.save(node);
sql = LoggedSql.stop();
sql.forEach(System.out::println);
}
@Test
public void testQuery() throws Exception {
createTestData();