diff --git a/core/testsuite/src/main/hibernate/com/blazebit/persistence/testsuite/entity/Person.java b/core/testsuite/src/main/hibernate/com/blazebit/persistence/testsuite/entity/Person.java index 8ef94571f9..c4d5509271 100644 --- a/core/testsuite/src/main/hibernate/com/blazebit/persistence/testsuite/entity/Person.java +++ b/core/testsuite/src/main/hibernate/com/blazebit/persistence/testsuite/entity/Person.java @@ -92,7 +92,7 @@ public void setOwnedDocuments(Set ownedDocuments) { @OneToMany @JoinColumn( - name = "owner_id", + name = "responsible_person_id", referencedColumnName = "id" ) public Set getOwnedDocuments2() { diff --git a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/Document.java b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/Document.java index 8bdcfb3bd4..c535c64f49 100644 --- a/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/Document.java +++ b/core/testsuite/src/main/java/com/blazebit/persistence/testsuite/entity/Document.java @@ -24,6 +24,7 @@ import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.FetchType; +import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; @@ -435,6 +436,7 @@ public void setParent(Document parent) { } @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "responsible_person_id") public Person getResponsiblePerson() { return responsiblePerson; } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/ScalarTargetResolvingExpressionVisitor.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/ScalarTargetResolvingExpressionVisitor.java index 3ad6bd9f4e..80c7386dda 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/ScalarTargetResolvingExpressionVisitor.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/ScalarTargetResolvingExpressionVisitor.java @@ -370,8 +370,9 @@ public void visit(MapKeyExpression expression) { if (!(currentPosition.getAttribute() instanceof MapAttribute)) { invalid(expression, "Does not resolve to java.util.Map!"); } else { - currentPosition.setAttribute(new MapKeyAttribute<>((MapAttribute) currentPosition.getAttribute())); - currentPosition.setCurrentType(((MapAttribute) currentPosition.getAttribute()).getKeyType()); + MapKeyAttribute keyAttribute = new MapKeyAttribute<>((MapAttribute) currentPosition.getAttribute()); + currentPosition.setAttribute(keyAttribute); + currentPosition.setCurrentType(keyAttribute.getType()); } } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/flush/CollectionAttributeFlusher.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/flush/CollectionAttributeFlusher.java index 7e8253ed87..fe49bc5db4 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/flush/CollectionAttributeFlusher.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/flush/CollectionAttributeFlusher.java @@ -382,20 +382,38 @@ protected boolean deleteElements(UpdateContext context, Object ownerView, Object Collection removedObjects = Collections.emptyList(); if (fusedCollectionActions != null) { if (fusedCollectionActions.getRemoveCount() > 0) { - deleteCb = createCollectionDeleter(context); + if (inverseFlusher == null) { + deleteCb = createCollectionDeleter(context); + } if (removeSpecific) { - String entityIdAttributeName = elementDescriptor.getEntityIdAttributeName(); - if (entityIdAttributeName != null) { - removedObjects = appendRemoveSpecific(context, deleteCb, fusedCollectionActions); - removedAll = false; - if (removedObjects.isEmpty()) { - deleteCb = null; + if (inverseFlusher == null) { + String entityIdAttributeName = elementDescriptor.getEntityIdAttributeName(); + if (entityIdAttributeName != null) { + removedObjects = appendRemoveSpecific(context, deleteCb, fusedCollectionActions); + removedAll = false; + if (removedObjects.isEmpty()) { + deleteCb = null; + } } + } else { + for (Object o : fusedCollectionActions.getRemoved(context)) { + inverseFlusher.flushQuerySetElement(context, o, ownerView, null, null, null); + } + } + } else if (inverseFlusher != null) { + for (Object o : value) { + inverseFlusher.flushQuerySetElement(context, o, ownerView, null, null, null); } + return true; } } else { removedAll = false; } + } else if (inverseFlusher != null) { + for (Object o : value) { + inverseFlusher.flushQuerySetElement(context, o, ownerView, null, null, null); + } + return true; } else { deleteCb = createCollectionDeleter(context); } @@ -422,7 +440,7 @@ protected boolean deleteElements(UpdateContext context, Object ownerView, Object protected void addElements(UpdateContext context, Object ownerView, Object view, Collection removedAllObjects, boolean flushAtOnce, V value, List embeddablesToUpdate, FusedCollectionActions fusedCollectionActions) { Collection elementsToAdd; if (fusedCollectionActions == null || !removedAllObjects.isEmpty()) { - if (elementDescriptor.getViewToEntityMapper() == null) { + if (elementDescriptor.getViewToEntityMapper() == null || inverseFlusher != null) { elementsToAdd = (Collection) value; } else { elementsToAdd = getEntityReferencesForCollectionOperation(context, (Collection) value); @@ -430,59 +448,69 @@ protected void addElements(UpdateContext context, Object ownerView, Object view, removedAllObjects.removeAll(value); } else { removedAllObjects.removeAll(fusedCollectionActions.getAdded()); - elementsToAdd = fusedCollectionActions.getAdded(context); + if (inverseFlusher == null) { + elementsToAdd = fusedCollectionActions.getAdded(context); + } else { + elementsToAdd = fusedCollectionActions.getAdded(); + } } if (elementsToAdd == null || elementsToAdd.isEmpty() || elementsToAdd.size() == 1 && elementsToAdd.iterator().next() == null) { return; } String mapping = getMapping(); - InsertCriteriaBuilder insertCb = context.getEntityViewManager().getCriteriaBuilderFactory().insertCollection(context.getEntityManager(), ownerEntityClass, mapping); + if (inverseFlusher == null) { + InsertCriteriaBuilder insertCb = context.getEntityViewManager().getCriteriaBuilderFactory().insertCollection(context.getEntityManager(), ownerEntityClass, mapping); - String entityIdAttributeName = elementDescriptor.getEntityIdAttributeName(); - if (flushAtOnce) { - if (entityIdAttributeName == null) { - insertCb.fromValues(ownerEntityClass, mapping, "val", elementsToAdd); + String entityIdAttributeName = elementDescriptor.getEntityIdAttributeName(); + if (flushAtOnce) { + if (entityIdAttributeName == null) { + insertCb.fromValues(ownerEntityClass, mapping, "val", elementsToAdd); + } else { + insertCb.fromIdentifiableValues((Class) elementDescriptor.getJpaType(), "val", elementsToAdd); + } } else { - insertCb.fromIdentifiableValues((Class) elementDescriptor.getJpaType(), "val", elementsToAdd); + if (entityIdAttributeName == null) { + insertCb.fromValues(ownerEntityClass, mapping, "val", 1); + } else { + insertCb.fromIdentifiableValues((Class) elementDescriptor.getJpaType(), "val", 1); + } } - } else { - if (entityIdAttributeName == null) { - insertCb.fromValues(ownerEntityClass, mapping, "val", 1); - } else { - insertCb.fromIdentifiableValues((Class) elementDescriptor.getJpaType(), "val", 1); + for (int i = 0; i < ownerIdBindFragments.length; i += 2) { + insertCb.bind(ownerIdBindFragments[i]).select(ownerIdBindFragments[i + 1]); } - } - for (int i = 0; i < ownerIdBindFragments.length; i += 2) { - insertCb.bind(ownerIdBindFragments[i]).select(ownerIdBindFragments[i + 1]); - } - insertCb.bind(mapping).select("val"); - Query insertQuery = insertCb.getQuery(); - ownerIdFlusher.flushQuery(context, null, insertQuery, ownerView, view, ownerIdFlusher.getViewAttributeAccessor().getValue(ownerView), null); + insertCb.bind(mapping).select("val"); + Query insertQuery = insertCb.getQuery(); + ownerIdFlusher.flushQuery(context, null, insertQuery, ownerView, view, ownerIdFlusher.getViewAttributeAccessor().getValue(ownerView), null); - boolean checkTransient = elementDescriptor.isJpaEntity() && !elementDescriptor.shouldJpaPersist(); - if (flushAtOnce) { - if (checkTransient) { + boolean checkTransient = elementDescriptor.isJpaEntity() && !elementDescriptor.shouldJpaPersist(); + if (flushAtOnce) { + if (checkTransient) { + for (Object o : elementsToAdd) { + if (elementDescriptor.getBasicUserType().shouldPersist(o)) { + throw new IllegalStateException("Collection " + attributeName + " references an unsaved transient instance - save the transient instance before flushing: " + o); + } + } + } + insertQuery.executeUpdate(); + } else { + // TODO: Use batching when we implement #657 + Object[] singletonArray = new Object[1]; + List singletonList = Arrays.asList(singletonArray); for (Object o : elementsToAdd) { - if (elementDescriptor.getBasicUserType().shouldPersist(o)) { - throw new IllegalStateException("Collection " + attributeName + " references an unsaved transient instance - save the transient instance before flushing: " + o); + if (o != null) { + if (checkTransient && elementDescriptor.getBasicUserType().shouldPersist(o)) { + throw new IllegalStateException("Collection " + attributeName + " references an unsaved transient instance - save the transient instance before flushing: " + o); + } + singletonArray[0] = o; + insertQuery.setParameter("val", singletonList); + insertQuery.executeUpdate(); } } } - insertQuery.executeUpdate(); } else { - // TODO: Use batching when we implement #657 - Object[] singletonArray = new Object[1]; - List singletonList = Arrays.asList(singletonArray); for (Object o : elementsToAdd) { - if (o != null) { - if (checkTransient && elementDescriptor.getBasicUserType().shouldPersist(o)) { - throw new IllegalStateException("Collection " + attributeName + " references an unsaved transient instance - save the transient instance before flushing: " + o); - } - singletonArray[0] = o; - insertQuery.setParameter("val", singletonList); - insertQuery.executeUpdate(); - } + inverseFlusher.flushQuerySetElement(context, o, null, ownerView, null, null); } } } diff --git a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/EntityViewUpdateSubviewInverseSimpleTest.java b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/EntityViewUpdateSubviewInverseSimpleTest.java index 458a9b0bab..f4eb5e761c 100644 --- a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/EntityViewUpdateSubviewInverseSimpleTest.java +++ b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/EntityViewUpdateSubviewInverseSimpleTest.java @@ -34,8 +34,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; /** @@ -75,6 +73,7 @@ public void testAddNewElementToCollection() { // When UpdatableDocumentView document = evm.create(UpdatableDocumentView.class); document.setName("newDoc123"); + document.setOwner(getP1View(PersonIdView.class)); newPerson.getOwnedDocuments2().add(document); update(newPerson); @@ -84,7 +83,7 @@ public void testAddNewElementToCollection() { // Then restartTransaction(); Document newDocument = em.find(Document.class, document.getId()); - Assert.assertEquals(newPerson.getId(), newDocument.getOwner().getId()); + Assert.assertEquals(newPerson.getId(), newDocument.getResponsiblePerson().getId()); } @Test @@ -94,6 +93,7 @@ public void testReplaceCollection() { newPerson.setName("newPers1"); UpdatableDocumentView document = evm.create(UpdatableDocumentView.class); document.setName("newDoc123"); + document.setOwner(getP1View(PersonIdView.class)); newPerson.getOwnedDocuments2().add(document); update(newPerson); @@ -104,7 +104,7 @@ public void testReplaceCollection() { // Then restartTransaction(); Document newDocument = em.find(Document.class, document.getId()); - Assert.assertEquals(newPerson.getId(), newDocument.getOwner().getId()); + Assert.assertEquals(newPerson.getId(), newDocument.getResponsiblePerson().getId()); } @Override diff --git a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/model/UpdatableDocumentView.java b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/model/UpdatableDocumentView.java index 5f498697f6..c5ebcda6e5 100644 --- a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/model/UpdatableDocumentView.java +++ b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/update/subview/inverse/simple/model/UpdatableDocumentView.java @@ -26,11 +26,14 @@ * @author Christian Beikov * @since 1.3.0 */ -@CreatableEntityView(excludedEntityAttributes = { "owner", "idx", "age" }) +@CreatableEntityView(excludedEntityAttributes = { "idx", "age" }) @UpdatableEntityView @EntityView(Document.class) public interface UpdatableDocumentView extends DocumentIdView { String getName(); void setName(String name); + + PersonIdView getOwner(); + void setOwner(PersonIdView owner); }