Skip to content

Commit

Permalink
[Blazebit#571] Make isJoinable/isCompositeNode and dependents JPA ven…
Browse files Browse the repository at this point in the history
…dor specific
  • Loading branch information
jwgmeligmeyling committed Sep 4, 2018
1 parent 5ec5f56 commit 6d9ba33
Show file tree
Hide file tree
Showing 24 changed files with 510 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.blazebit.persistence.parser;
package com.blazebit.persistence.spi;

import javax.persistence.metamodel.Attribute;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2014 - 2018 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.blazebit.persistence.spi;

import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;

public interface JpaMetamodelUtils {

This comment has been minimized.

Copy link
@beikov

beikov Sep 4, 2018

Collaborator

JpaMetamodelAccessor


AttributePath getAttributePath(Metamodel metamodel, ManagedType<?> type, String attributePath);

AttributePath getBasicAttributePath(Metamodel metamodel, ManagedType<?> type, String attributePath);

AttributePath getJoinTableCollectionAttributePath(Metamodel metamodel, EntityType<?> type, String attributePath, String collectionName);

boolean isJoinable(Attribute<?, ?> attr);

boolean isCompositeNode(Attribute<?, ?> attr);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* A JPA provider implementation provides information about which features are supported by a JPA implementation.
*
* @author Christian Beikov
* O@author Christian Beikov
* @since 1.2.0
*/
public interface JpaProvider {
Expand Down Expand Up @@ -447,6 +447,13 @@ public interface JpaProvider {
*/
public Object getIdentifier(Object entity);

/**
* Returns the JpaMetamodelUtils for this JPA vendor.
* @return the JpaMetamodelUtils for this JPA vendor
* @since 1.3.0
*/
public JpaMetamodelUtils getJpaMetamodelUtils();

This comment has been minimized.

Copy link
@beikov

beikov Sep 4, 2018

Collaborator

Adapt to the new name JpaMetamodelAccessor


/**
* The possible locations of a constraint.
*
Expand All @@ -466,4 +473,5 @@ public static enum ConstraintType {
*/
WHERE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ protected List<String> prepareAndGetAttributes() {

ExtendedAttribute attributeEntry = attributeEntries.get(attributeName);
List<Attribute<?, ?>> attributePath = attributeEntry.getAttributePath();
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
attributes.add(attributeName);

if (JpaMetamodelUtils.isJoinable(attributePath.get(attributePath.size() - 1))) {
if (jpaMetamodelUtils.isJoinable(attributePath.get(attributePath.size() - 1))) {
List<String> idOrUniqueKeyProps = cbf.getJpaProvider().getIdentifierOrUniqueKeyEmbeddedPropertyNames(cteType, attributeName);
// We have to map *-to-one relationships to their id or unique props
// NOTE: Since we are talking about *-to-ones, the expression can only be a path to an object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ protected AbstractCommonQueryBuilder(AbstractCommonQueryBuilder<QueryResultType,
this.fromClassExplicitlySet = builder.fromClassExplicitlySet;

this.subqueryInitFactory = joinManager.getSubqueryInitFactory();
SplittingVisitor splittingVisitor = new SplittingVisitor(mainQuery.metamodel);
SplittingVisitor splittingVisitor = new SplittingVisitor(mainQuery.metamodel, mainQuery.jpaProvider);
this.embeddableSplittingVisitor = new EmbeddableSplittingVisitor(mainQuery.metamodel, splittingVisitor);
this.groupByExpressionGatheringVisitor = new GroupByExpressionGatheringVisitor(false, mainQuery.dbmsDialect);
this.functionalDependencyAnalyzerVisitor = new FunctionalDependencyAnalyzerVisitor(mainQuery.metamodel, splittingVisitor);
Expand Down Expand Up @@ -305,7 +305,7 @@ protected AbstractCommonQueryBuilder(MainQuery mainQuery, QueryContext queryCont
}

this.subqueryInitFactory = joinManager.getSubqueryInitFactory();
SplittingVisitor splittingVisitor = new SplittingVisitor(mainQuery.metamodel);
SplittingVisitor splittingVisitor = new SplittingVisitor(mainQuery.metamodel, mainQuery.jpaProvider);
this.embeddableSplittingVisitor = new EmbeddableSplittingVisitor(mainQuery.metamodel, splittingVisitor);
this.groupByExpressionGatheringVisitor = new GroupByExpressionGatheringVisitor(false, mainQuery.dbmsDialect);
this.functionalDependencyAnalyzerVisitor = new FunctionalDependencyAnalyzerVisitor(mainQuery.metamodel, splittingVisitor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ private void addAttributes(String prefix, Set<SingularAttribute<?, ?>> attribute
sb.setLength(0);
rootNode.appendDeReference(sb, attributeName);
PathExpression expression = (PathExpression) rootNode.createExpression(attributeName);
expression.setPathReference(new SimplePathReference(rootNode, attributeName, getMetamodel().type(JpaMetamodelUtils.getAttributePath(getMetamodel(), rootNode.getManagedType(), attributeName).getAttributeClass())));
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
expression.setPathReference(new SimplePathReference(rootNode, attributeName, getMetamodel().type(jpaMetamodelUtils.getAttributePath(getMetamodel(), rootNode.getManagedType(), attributeName).getAttributeClass())));
resolvedExpressions.add(new ResolvedExpression(sb.toString(), expression));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import com.blazebit.persistence.impl.query.EntityFunctionNode;
import com.blazebit.persistence.impl.query.QuerySpecification;
import com.blazebit.persistence.impl.query.ReturningCollectionInsertModificationQuerySpecification;
import com.blazebit.persistence.parser.AttributePath;
import com.blazebit.persistence.spi.AttributePath;
import com.blazebit.persistence.parser.QualifiedAttribute;
import com.blazebit.persistence.parser.util.JpaMetamodelUtils;
import com.blazebit.persistence.impl.util.SqlUtils;
Expand Down Expand Up @@ -86,7 +86,8 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external

@Override
protected void addBind(String attributeName) {
AttributePath attributePath = JpaMetamodelUtils.getJoinTableCollectionAttributePath(getMetamodel(), entityType, attributeName, collectionName);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributePath attributePath = jpaMetamodelUtils.getJoinTableCollectionAttributePath(getMetamodel(), entityType, attributeName, collectionName);
StringBuilder sb = new StringBuilder();
List<Attribute<?, ?>> attributes = attributePath.getAttributes();
Attribute<?, ?> attribute = attributes.get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import com.blazebit.persistence.impl.query.ModificationQuerySpecification;
import com.blazebit.persistence.impl.query.QuerySpecification;
import com.blazebit.persistence.impl.query.ReturningModificationQuerySpecification;
import com.blazebit.persistence.parser.AttributePath;
import com.blazebit.persistence.spi.AttributePath;
import com.blazebit.persistence.parser.util.JpaMetamodelUtils;
import com.blazebit.persistence.spi.DbmsModificationState;
import com.blazebit.persistence.spi.DbmsStatementType;
Expand Down Expand Up @@ -327,7 +327,8 @@ public <Z> TypedQuery<ReturningResult<Z>> getWithReturningQuery(String attribute
throw new IllegalArgumentException("Invalid empty attribute");
}

AttributePath attrPath = JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attribute);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributePath attrPath = jpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attribute);

if (!type.isAssignableFrom(attrPath.getAttributeClass())) {
throw new IllegalArgumentException("The given expected field type is not of the expected type: " + attrPath.getAttributeClass().getName());
Expand Down Expand Up @@ -426,7 +427,8 @@ public SimpleReturningBuilder returning(String modificationQueryAttribute) {
modificationQueryAttribute = idAttribute.getName();
}

List<Attribute<?, ?>> attributePath = JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute).getAttributes();
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
List<Attribute<?, ?>> attributePath = jpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute).getAttributes();
if (returningAttributes.put(modificationQueryAttribute, attributePath) != null) {
throw new IllegalArgumentException("The entity attribute [" + modificationQueryAttribute + "] has already been returned!");
}
Expand Down Expand Up @@ -465,7 +467,8 @@ public X returning(String cteAttribute, String modificationQueryAttribute) {
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getSingleIdAttribute(entityType);
modificationQueryAttribute = idAttribute.getName();
} else {
AttributePath queryAttributePath = JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributePath queryAttributePath = jpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute);
queryAttrType = queryAttributePath.getAttributeClass();
}

Expand Down Expand Up @@ -512,8 +515,9 @@ public CTEInfo createCTEInfo() {
if (attributes[i].isEmpty()) {
throw new IllegalArgumentException("empty attribute at position " + i);
}

attrs.add(JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attributes[i]).getAttributes());

com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
attrs.add(jpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attributes[i]).getAttributes());
}

return attrs;
Expand Down Expand Up @@ -599,7 +603,8 @@ private TypedQuery<Object[]> getExampleQuery(List<List<Attribute<?, ?>>> attribu
throw new IllegalArgumentException("Returning the query attribute [" + lastPathElem.getName() + "] is not supported by the dbms, only generated keys can be returned!");
}

if (JpaMetamodelUtils.isJoinable(lastPathElem)) {
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
if (jpaMetamodelUtils.isJoinable(lastPathElem)) {
sb.append(entityAlias).append('.');
// We have to map *-to-one relationships to their ids
EntityType<?> type = mainQuery.metamodel.entity(JpaMetamodelUtils.resolveFieldClass(entityType.getJavaType(), lastPathElem));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.blazebit.persistence.ReturningBuilder;
import com.blazebit.persistence.ReturningObjectBuilder;
import com.blazebit.persistence.ReturningResult;
import com.blazebit.persistence.parser.AttributePath;
import com.blazebit.persistence.spi.AttributePath;
import com.blazebit.persistence.parser.QualifiedAttribute;
import com.blazebit.persistence.parser.SimpleQueryGenerator;
import com.blazebit.persistence.parser.expression.Expression;
Expand Down Expand Up @@ -76,7 +76,8 @@ public AbstractUpdateCollectionCriteriaBuilder(AbstractUpdateCollectionCriteriaB
@Override
protected String checkAttribute(String attributeName) {
// Assert the attribute exists and "clean" the attribute path
AttributePath attributePath = JpaMetamodelUtils.getJoinTableCollectionAttributePath(getMetamodel(), entityType, attributeName, collectionName);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributePath attributePath = jpaMetamodelUtils.getJoinTableCollectionAttributePath(getMetamodel(), entityType, attributeName, collectionName);
StringBuilder sb = new StringBuilder();
for (Attribute<?, ?> attribute : attributePath.getAttributes()) {
// Replace the collection name with the alias for easier processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ public void onInitiatorStarted(SubqueryInitiator<?> initiator) {

protected String checkAttribute(String attributeName) {
// Just do that to assert the attribute exists
JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attributeName);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
jpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, attributeName);
Expression attributeExpression = setAttributes.get(attributeName);

if (attributeExpression != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.blazebit.persistence.spi.ExtendedAttribute;
import com.blazebit.persistence.spi.ExtendedManagedType;
import com.blazebit.persistence.spi.JoinTable;
import com.blazebit.persistence.spi.JpaMetamodelUtils;
import com.blazebit.persistence.spi.JpaProvider;

import javax.persistence.EntityManager;
Expand Down Expand Up @@ -307,4 +308,9 @@ public List<String> getIdentifierOrUniqueKeyEmbeddedPropertyNames(EntityType<?>
public Object getIdentifier(Object entity) {
return jpaProvider.getIdentifier(entity);
}

@Override
public JpaMetamodelUtils getJpaMetamodelUtils() {
return jpaProvider.getJpaMetamodelUtils();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2310,13 +2310,14 @@ private JoinResult implicitJoinSingle(JoinNode baseNode, String attributeName, b
lazy = true;
}
} else {
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributeHolder attributeHolder = JpaUtils.getAttributeForJoining(metamodel, baseNodeType, expressionFactory.createJoinPathExpression(attributeName), baseNode.getAlias());
Attribute<?, ?> attr = attributeHolder.getAttribute();
if (attr == null) {
throw new IllegalArgumentException("Field with name " + attributeName + " was not found within class " + JpaMetamodelUtils.getTypeName(baseNodeType));
}
if (JpaMetamodelUtils.isJoinable(attr)) {
if (JpaMetamodelUtils.isCompositeNode(attr)) {
if (jpaMetamodelUtils.isJoinable(attr)) {
if (jpaMetamodelUtils.isCompositeNode(attr)) {
throw new IllegalArgumentException("No object leaf allowed but " + attributeName + " is an object leaf");
} else {
final JoinResult newBaseNodeResult = implicitJoinSingle(baseNode, attributeName, false);
Expand Down Expand Up @@ -2349,13 +2350,14 @@ private JoinType getModelAwareType(JoinNode baseNode, Attribute<?, ?> attr) {
private JoinResult createOrUpdateNode(JoinNode baseNode, List<String> joinRelationAttributes, String treatType, String alias, JoinType joinType, boolean implicit, boolean defaultJoin) {
Type<?> baseNodeType = baseNode.getNodeType();
String joinRelationName = StringUtils.join(".", joinRelationAttributes);
com.blazebit.persistence.spi.JpaMetamodelUtils jpaMetamodelUtils = mainQuery.jpaProvider.getJpaMetamodelUtils();
AttributeHolder attrJoinResult = JpaUtils.getAttributeForJoining(metamodel, baseNodeType, expressionFactory.createJoinPathExpression(joinRelationName), baseNode.getAlias());
Attribute<?, ?> attr = attrJoinResult.getAttribute();
if (attr == null) {
throw new IllegalArgumentException("Field with name " + joinRelationName + " was not found within class " + JpaMetamodelUtils.getTypeName(baseNodeType));
}

if (!JpaMetamodelUtils.isJoinable(attr)) {
if (!jpaMetamodelUtils.isJoinable(attr)) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine(new StringBuilder("Field with name ").append(joinRelationName)
.append(" of class ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.blazebit.persistence.parser.expression.PathExpression;
import com.blazebit.persistence.parser.expression.PropertyExpression;
import com.blazebit.persistence.parser.util.JpaMetamodelUtils;
import com.blazebit.persistence.spi.JpaProvider;

import javax.persistence.metamodel.Type;
import java.util.ArrayList;
Expand All @@ -36,11 +37,13 @@
public class SplittingVisitor extends LazyCopyingResultVisitorAdapter {

private final EntityMetamodel metamodel;
private final JpaProvider jpaProvider;
private PathExpression expressionToSplit;
private String subAttribute;

public SplittingVisitor(EntityMetamodel metamodel) {
public SplittingVisitor(EntityMetamodel metamodel, JpaProvider jpaProvider) {
this.metamodel = metamodel;
this.jpaProvider = jpaProvider;
}

@Override
Expand All @@ -53,7 +56,7 @@ public Expression visit(PathExpression expression) {

String field = expression.getField() + "." + subAttribute;
JoinNode node = (JoinNode) expression.getBaseNode();
Class<?> fieldClass = JpaMetamodelUtils.getAttributePath(metamodel, node.getManagedType(), field).getAttributeClass();
Class<?> fieldClass = jpaProvider.getJpaMetamodelUtils().getAttributePath(metamodel, node.getManagedType(), field).getAttributeClass();
Type<?> fieldType = metamodel.type(fieldClass);

return new PathExpression(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ private Type<?> getType(Type<?> baseType, Attribute<?, ?> attribute) {
public void visit(PropertyExpression expression) {
String property = expression.getProperty();
if (currentPosition.getCurrentType() instanceof BasicType<?>) {

This comment has been minimized.

Copy link
@beikov

beikov Sep 4, 2018

Collaborator

Superfluous blank line

throw new IllegalArgumentException("Can't access property '" + property + "' on basic type '" + JpaMetamodelUtils.getTypeName(currentPosition.getCurrentType()) + "'. Did you forget to add the embeddable type to your persistence.xml?");
}
Attribute<?, ?> attribute = JpaMetamodelUtils.getAttribute((ManagedType<?>) currentPosition.getCurrentType(), property);
Expand Down
Loading

0 comments on commit 6d9ba33

Please sign in to comment.