diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/metamodel/MethodAttributeMapping.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/metamodel/MethodAttributeMapping.java index 4796e01c88..e7a477c2f7 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/metamodel/MethodAttributeMapping.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/metamodel/MethodAttributeMapping.java @@ -20,7 +20,6 @@ import com.blazebit.persistence.impl.util.JpaMetamodelUtils; import com.blazebit.persistence.view.CascadeType; import com.blazebit.persistence.view.InverseRemoveStrategy; -import com.blazebit.persistence.view.Mapping; import com.blazebit.persistence.view.MappingCorrelated; import com.blazebit.persistence.view.MappingCorrelatedSimple; import com.blazebit.persistence.view.MappingParameter; @@ -236,6 +235,8 @@ public String determineMappedBy(ManagedType managedType, String mapping, Meta return mappedBy; } + mappedByResolved = true; + if (mapping.isEmpty()) { return null; } @@ -261,7 +262,7 @@ public String determineMappedBy(ManagedType managedType, String mapping, Meta return null; } } - return context.getJpaProvider().getMappedBy((EntityType) managedType, mapping); + return mappedBy = context.getJpaProvider().getMappedBy((EntityType) managedType, mapping); } catch (IllegalArgumentException ex) { // if the mapping is invalid, we skip the determination as the error will be analyzed further at a later stage return null; @@ -369,12 +370,6 @@ private static String methodReference(Method method) { return (AbstractMethodAttribute) attribute; } - if (!mappedByResolved && mapping instanceof Mapping) { - ManagedType managedType = context.getEntityMetamodel().getManagedType(viewType.getEntityClass()); - mappedBy = determineMappedBy(managedType, AbstractAttribute.stripThisFromMapping(((Mapping) mapping).value()), context); - } - mappedByResolved = true; - boolean correlated = mapping instanceof MappingCorrelated || mapping instanceof MappingCorrelatedSimple; if (isCollection) { diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/type/MutableBasicUserTypeRegistry.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/type/MutableBasicUserTypeRegistry.java index 89a90d6b97..108495ca29 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/type/MutableBasicUserTypeRegistry.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/type/MutableBasicUserTypeRegistry.java @@ -115,25 +115,25 @@ public MutableBasicUserTypeRegistry() { // NOTE: keep this in sync with 09_basic_user_type.adoc + Map, TypeConverter> map = new HashMap<>(); + map.put(Blob.class, BlobTypeConverter.INSTANCE); + converters.put(Blob.class, map); + map = new HashMap<>(); + map.put(Clob.class, ClobTypeConverter.INSTANCE); + converters.put(Clob.class, map); + map = new HashMap<>(); + map.put(NClob.class, NClobTypeConverter.INSTANCE); + converters.put(NClob.class, map); + // Java 8 optional types try { - Map, TypeConverter> map = new HashMap<>(); + map = new HashMap<>(); map.put(Object.class, new OptionalTypeConverter()); converters.put(Class.forName("java.util.Optional"), map); // TODO: OptionalInt etc. - map = new HashMap<>(); - map.put(Blob.class, BlobTypeConverter.INSTANCE); - converters.put(Blob.class, map); - map = new HashMap<>(); - map.put(Clob.class, ClobTypeConverter.INSTANCE); - converters.put(Clob.class, map); - map = new HashMap<>(); - map.put(NClob.class, NClobTypeConverter.INSTANCE); - converters.put(NClob.class, map); } catch (ClassNotFoundException ex) { // If they aren't found, we ignore them } - } @Override diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/ResetInitialStateSynchronization.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/ResetInitialStateSynchronization.java index 25ec90fb6f..7850b18d68 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/ResetInitialStateSynchronization.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/update/ResetInitialStateSynchronization.java @@ -66,7 +66,6 @@ public void addRecordingMap(RecordingMap recordingMap, List columnIterator = collection.getKey().getColumnIterator(); + List columnNames = new ArrayList<>(); + while (columnIterator.hasNext()) { + Column column = columnIterator.next(); + columnNames.add(column.getName()); + } + + OneToMany oneToMany = (OneToMany) collection.getElement(); + Iterator propertyIterator = oneToMany.getAssociatedClass().getPropertyIterator(); + while (propertyIterator.hasNext()) { + Property property = (Property) propertyIterator.next(); + if (property.getValue() instanceof ToOne) { + ToOne toOne = (ToOne) property.getValue(); + if (ownerEntityName.equals(toOne.getReferencedEntityName()) + && matches(columnNames, collection.getKey().getColumnIterator())) { + return property.getName(); + } + } + } + + return null; + } + + private boolean matches(List columns, Iterator iter) { + for (int i = 0; iter.hasNext(); i++) { + Column column = iter.next(); + if (i == columns.size() || !columns.get(i).equals(column.getName())) { + return false; + } + } + + return true; } @Override @@ -49,7 +98,7 @@ public String getMappedByProperty() { protected CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session) { // Hibernate before 4 couldn't find the correct from clause StringBuilder sb = null; - String subselectQuery = subselect.toSubselectString( getCollectionType().getLHSPropertyName() ); + String subselectQuery = subselect.toSubselectString(getCollectionType().getLHSPropertyName()); int parens = 0; for (int i = 0; i < subselectQuery.length(); i++) { @@ -75,13 +124,13 @@ protected CollectionInitializer createSubselectInitializer(SubselectFetch subsel } return new CustomSubselectCollectionLoader( - this, - subselectQuery, - subselect.getResult(), - subselect.getQueryParameters(), - subselect.getNamedParameterLocMap(), - session.getFactory(), - session.getLoadQueryInfluencers() + this, + subselectQuery, + subselect.getResult(), + subselect.getQueryParameters(), + subselect.getNamedParameterLocMap(), + session.getFactory(), + session.getLoadQueryInfluencers() ); } } diff --git a/integration/hibernate-4.2/src/main/java/com/blazebit/persistence/impl/hibernate/CustomOneToManyPersister.java b/integration/hibernate-4.2/src/main/java/com/blazebit/persistence/impl/hibernate/CustomOneToManyPersister.java index a137dab05a..63218e2d0a 100644 --- a/integration/hibernate-4.2/src/main/java/com/blazebit/persistence/impl/hibernate/CustomOneToManyPersister.java +++ b/integration/hibernate-4.2/src/main/java/com/blazebit/persistence/impl/hibernate/CustomOneToManyPersister.java @@ -25,8 +25,16 @@ import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.mapping.Collection; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.OneToMany; +import org.hibernate.mapping.Property; +import org.hibernate.mapping.ToOne; import org.hibernate.persister.collection.OneToManyPersister; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * * @author Christian Beikov @@ -38,7 +46,48 @@ public class CustomOneToManyPersister extends OneToManyPersister implements Cust public CustomOneToManyPersister(Collection collection, CollectionRegionAccessStrategy cacheAccessStrategy, Configuration cfg, SessionFactoryImplementor factory) throws MappingException, CacheException { super(collection, cacheAccessStrategy, cfg, factory); - this.mappedByProperty = collection.getReferencedPropertyName(); + String referencedPropertyName = collection.getReferencedPropertyName(); + if (referencedPropertyName == null && collection.isInverse()) { + referencedPropertyName = findMappedByProperty(collection); + } + this.mappedByProperty = referencedPropertyName; + } + + @SuppressWarnings("unchecked") + private String findMappedByProperty(Collection collection) { + String ownerEntityName = collection.getOwnerEntityName(); + Iterator columnIterator = collection.getKey().getColumnIterator(); + List columnNames = new ArrayList<>(); + while (columnIterator.hasNext()) { + Column column = columnIterator.next(); + columnNames.add(column.getName()); + } + + OneToMany oneToMany = (OneToMany) collection.getElement(); + Iterator propertyIterator = oneToMany.getAssociatedClass().getPropertyIterator(); + while (propertyIterator.hasNext()) { + Property property = (Property) propertyIterator.next(); + if (property.getValue() instanceof ToOne) { + ToOne toOne = (ToOne) property.getValue(); + if (ownerEntityName.equals(toOne.getReferencedEntityName()) + && matches(columnNames, collection.getKey().getColumnIterator())) { + return property.getName(); + } + } + } + + return null; + } + + private boolean matches(List columns, Iterator iter) { + for (int i = 0; iter.hasNext(); i++) { + Column column = iter.next(); + if (i == columns.size() || !columns.get(i).equals(column.getName())) { + return false; + } + } + + return true; } @Override