Skip to content

Commit

Permalink
[Blazebit#509] Make use of Collection DML for collection flushers in …
Browse files Browse the repository at this point in the history
…updatable entity views
  • Loading branch information
beikov committed Oct 21, 2018
1 parent 0e08aa8 commit 5b29dbd
Show file tree
Hide file tree
Showing 341 changed files with 10,998 additions and 4,450 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Expand Up @@ -8,25 +8,31 @@ Not yet released

### New features

* Support for binding Embeddables directly to embeddable path expressions in CTE's
* Support for binding embeddables directly to embeddable path expressions in CTEs
* Support for binding associations that are part of an entities identifier
* Support for binding associations mapped by compound or foreign keys
* Using a comparator with `List` and `Collection` types in entity views will sort the collection after load
* Add option to force deduplication of elements in non-sets to `@CollectionMapping`
* Support `VALUES` clause with embeddable and most basic types
* Support for binding embeddable parameters in CTEs, insert and update queries
* Properly implement dirty state transfer when converting one entity view to another
* Added validation for `equals`/`hashCode` implementations of JPA managed types that are used within entity views which can be disabled with the property `com.blazebit.persistence.view.managed_type_validation_disabled`
* Add support for DeltaSpike Data 1.9
* Make use of Collection DML API when using the `QUERY` flush strategy in updatable entity views

### Bug fixes

* Using non-bags in entity views will now properly deduplicate elements
* Fix support for exists repository methods in Spring Data repositories
* Fix problems with count queries that require parameters in Spring Data repositories
* Properly set parent id on converted creatable subviews contained in inverse collections
* Fix type variable related issues with Spring Data Repositories
* Properly set parent id on converted creatable subviews contained in inverse collections
* Fix entity view build time validation error with certain inheritance mappings
* Fix problems with objects of wrong types being returned from standard repository methods with Spring Data 2.0+
* Fix various little issues related to embeddable handling in updatable entity views
* Fix support for mapping the inverse side of a `ManyToMany` as updatable collection
* Fix cycle detection for certain polymorphic entity view graphs

### Backwards-incompatible changes

Expand Down
Expand Up @@ -115,7 +115,7 @@
<property name="max" value="270"/>
</module>
<module name="ParameterNumber">
<property name="max" value="22"/>
<property name="max" value="25"/>
</module>

<!-- Checks for blocks. You know, those {}'s -->
Expand Down
Expand Up @@ -48,6 +48,14 @@ public interface ExtendedAttribute<X, Y> {
*/
public List<Attribute<?, ?>> getAttributePath();

/**
* Returns the path from the owning entity type to this attribute as string.
*
* @return The path to the attribute as string
* @since 1.3.0
*/
public String getAttributePathString();

/**
* Returns the element type of the attribute.
*
Expand Down
Expand Up @@ -16,6 +16,7 @@

package com.blazebit.persistence.spi;

import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.SingularAttribute;
import java.util.Map;
Expand All @@ -37,6 +38,22 @@ public interface ExtendedManagedType<X> {
*/
public ManagedType<X> getType();

/**
* Returns an entity type and path that owns this embeddable type via a singular attribute or null if there is none.
*
* @return An entity type and path that owns this embeddable type via a singular attribute or null if there is none
* @since 1.3.0
*/
public Map.Entry<EntityType<?>, String> getEmbeddableSingularOwner();

/**
* Returns an entity type and path that owns this embeddable type via a plural attribute or null if there is none.
*
* @return An entity type and path that owns this embeddable type via a plural attribute or null if there is none
* @since 1.3.0
*/
public Map.Entry<EntityType<?>, String> getEmbeddablePluralOwner();

/**
* Returns whether the type has a cascading delete cycle.
*
Expand Down Expand Up @@ -66,6 +83,14 @@ public interface ExtendedManagedType<X> {
*/
public Map<String, ExtendedAttribute<X, ?>> getAttributes();

/**
* Returns the owned extended attributes of the managed type.
*
* @return The owned extended attributes
* @since 1.3.0
*/
public Map<String, ExtendedAttribute<X, ?>> getOwnedAttributes();

/**
* Returns the extended attribute of the managed type for the given attribute name.
*
Expand Down
30 changes: 28 additions & 2 deletions core/api/src/main/java/com/blazebit/persistence/spi/JoinTable.java
Expand Up @@ -17,6 +17,7 @@
package com.blazebit.persistence.spi;

import java.util.Map;
import java.util.Set;

/**
* A structure for accessing join table information.
Expand All @@ -27,22 +28,27 @@
public class JoinTable {

private final String tableName;
private final Set<String> idAttributeNames;
private final Set<String> targetAttributeNames;
private final Map<String, String> idColumnMappings;
private final Map<String, String> keyColumnMappings;
private final Map<String, String> targetIdColumnMappings;

/**
* Constructs a JoinTable.
*
* @param tableName The join table name
* @param idAttributeNames The attribute names of the owning entity
* @param idColumnMappings The id column mappings
* @param keyColumnMappings The key column mappings
* @param targetAttributeNames The attribute names of the target entity
* @param targetIdColumnMappings The target id column mappings
*/
public JoinTable(String tableName, Map<String, String> idColumnMappings, Map<String, String> keyColumnMappings, Map<String, String> targetIdColumnMappings) {
public JoinTable(String tableName, Set<String> idAttributeNames, Map<String, String> idColumnMappings, Map<String, String> keyColumnMappings, Set<String> targetAttributeNames, Map<String, String> targetIdColumnMappings) {
this.tableName = tableName;
this.idAttributeNames = idAttributeNames;
this.idColumnMappings = idColumnMappings;
this.keyColumnMappings = keyColumnMappings;
this.targetAttributeNames = targetAttributeNames;
this.targetIdColumnMappings = targetIdColumnMappings;
}

Expand All @@ -55,6 +61,16 @@ public String getTableName() {
return tableName;
}

/**
* Returns the id attribute names of the owning entity that map to the join table.
*
* @return The owner entity id attribute names
* @since 1.3.0
*/
public Set<String> getIdAttributeNames() {
return idAttributeNames;
}

/**
* Returns the foreign key mappings of the join tables column names to the owner table column names.
* The keys are column names of the join table. Values are the column names of the owner table.
Expand All @@ -77,6 +93,16 @@ public Map<String, String> getKeyColumnMappings() {
return keyColumnMappings;
}

/**
* Returns the id attribute names of the target entity that map to the join table.
*
* @return The target entity id attribute names
* @since 1.3.0
*/
public Set<String> getTargetAttributeNames() {
return targetAttributeNames;
}

/**
* Returns the foreign key mappings of the join tables column names to the target table column names.
* The keys are column names of the join table. Values are the column names of the target table.
Expand Down
Expand Up @@ -220,6 +220,15 @@ public interface JpaProvider {
*/
public boolean supportsCountStar();

/**
* Returns an array with the column name of the discriminator of the given entity type and the discriminator value, or null.
*
* @param entityType The entity type
* @return The column name of the discriminator and the discriminator value, or null
* @since 1.3.0
*/
public String[] getDiscriminatorColumnCheck(EntityType<?> entityType);

/**
* Whether the join columns for the given attribute are in a foreign table.
*
Expand Down Expand Up @@ -248,6 +257,17 @@ public interface JpaProvider {
*/
public String[] getColumnNames(EntityType<?> ownerType, String attributeName);

/**
* Returns the column names of the attribute of the given entity type within the element collection.
*
* @param ownerType The owner of the attribute
* @param elementCollectionPath The path to the element collection within which the attribute is contained
* @param attributeName The attribute name
* @return The column names of the attribute
* @since 1.3.0
*/
public String[] getColumnNames(EntityType<?> ownerType, String elementCollectionPath, String attributeName);

/**
* Returns the SQL column type names of the given attribute of the given entity type.
*
Expand All @@ -257,6 +277,17 @@ public interface JpaProvider {
*/
public String[] getColumnTypes(EntityType<?> ownerType, String attributeName);

/**
* Returns the SQL column type names of the given attribute of the given entity type within the element collection.
*
* @param ownerType The owner of the attribute
* @param elementCollectionPath The path to the element collection within which the attribute is contained
* @param attributeName The attribute name
* @return The SQL column type names for the attribute
* @since 1.3.0
*/
public String[] getColumnTypes(EntityType<?> ownerType, String elementCollectionPath, String attributeName);

/**
* Returns where to put treat filters for a treat joined association of this attribute.
* This is for JPA providers that don't correctly filter the types.
Expand Down Expand Up @@ -320,6 +351,17 @@ public interface JpaProvider {
*/
public boolean isOrphanRemoval(ManagedType<?> ownerType, String attributeName);

/**
* Whether orphan removal is activated for the given attribute within the element collection.
*
* @param ownerType The declaring type of the attribute to check
* @param elementCollectionPath The path to the element collection within which the attribute is contained
* @param attributeName The name of the attribute to check
* @return True if orphan removal is activated, else false
* @since 1.3.0
*/
public boolean isOrphanRemoval(ManagedType<?> ownerType, String elementCollectionPath, String attributeName);

/**
* Whether delete cascading is activated for the given attribute.
*
Expand All @@ -329,6 +371,17 @@ public interface JpaProvider {
*/
public boolean isDeleteCascaded(ManagedType<?> ownerType, String attributeName);

/**
* Whether delete cascading is activated for the given attribute within the element collection.
*
* @param ownerType The declaring type of the attribute to check
* @param elementCollectionPath The path to the element collection within which the attribute is contained
* @param attributeName The name of the attribute to check
* @return True if delete cascading is activated, else false
* @since 1.3.0
*/
public boolean isDeleteCascaded(ManagedType<?> ownerType, String elementCollectionPath, String attributeName);

/**
* Returns whether the entity with the id is contained in the entity managers persistence context.
*
Expand Down Expand Up @@ -423,10 +476,27 @@ public interface JpaProvider {
/**
* Indicates whether the provider supports correlating inverse associations.
*
* @return true if needed, else false
* @since 1.3.0
*/
public boolean needsCorrelationPredicateWhenCorrelatingWithWhereClause();

/**
* Indicates whether the provider supports optimized natural id access.
*
* @return true if supported, else false
* @since 1.3.0
*/
public boolean supportsJoinElementCollectionsOnCorrelatedInverseAssociations();
public boolean supportsSingleValuedAssociationNaturalIdExpressions();

/**
* Indicates whether the provider needs to cutoff id properties when used as subpath of element collections.
* This is to be able to workaround https://hibernate.atlassian.net/browse/HHH-13045 .
*
* @return true if needed, else false
* @since 1.3.0
*/
public boolean needsElementCollectionIdCutoff();

/**
* Enables query result caching for the given query.
Expand All @@ -446,6 +516,17 @@ public interface JpaProvider {
*/
public List<String> getIdentifierOrUniqueKeyEmbeddedPropertyNames(EntityType<?> owner, String attributeName);

/**
* Get the identifier or unique key inverse properties of an association attribute within an element collection.
*
* @param owner The owning entity type
* @param elementCollectionPath The path to the element collection within which the attribute is contained
* @param attributeName The association attribute
* @return the identifier or unique key inverse properties of the association attribute
* @since 1.3.0
*/
public List<String> getIdentifierOrUniqueKeyEmbeddedPropertyNames(EntityType<?> owner, String elementCollectionPath, String attributeName);

/**
* Returns the identifier of the entity object.
*
Expand Down
Expand Up @@ -77,10 +77,10 @@ public AbstractCTECriteriaBuilder(MainQuery mainQuery, QueryContext queryContext
this.listener = listener;

this.cteType = mainQuery.metamodel.entity(clazz);
this.attributeEntries = mainQuery.metamodel.getManagedType(ExtendedManagedType.class, clazz).getAttributes();
this.attributeEntries = mainQuery.metamodel.getManagedType(ExtendedManagedType.class, clazz).getOwnedAttributes();
this.cteName = cteName;
this.bindingMap = new LinkedHashMap<String, Integer>(attributeEntries.size());
this.columnBindingMap = new LinkedHashMap<String, String>(attributeEntries.size());
this.bindingMap = new LinkedHashMap<>(attributeEntries.size());
this.columnBindingMap = new LinkedHashMap<>(attributeEntries.size());
this.subListener = new CTEBuilderListenerImpl();
}

Expand Down Expand Up @@ -214,7 +214,7 @@ protected List<String> prepareAndGetAttributes() {
final String attributeName = attributeQueue.remove();
Integer tupleIndex = bindingMap.get(attributeName);

final ExtendedAttribute attributeEntry = attributeEntries.get(attributeName);
final ExtendedAttribute<?, ?> attributeEntry = attributeEntries.get(attributeName);
final List<Attribute<?, ?>> attributePath = attributeEntry.getAttributePath();
final JpaMetamodelAccessor jpaMetamodelAccessor = mainQuery.jpaProvider.getJpaMetamodelAccessor();
final Attribute<?, ?> lastAttribute = attributePath.get(attributePath.size() - 1);
Expand Down

0 comments on commit 5b29dbd

Please sign in to comment.