Skip to content

Commit

Permalink
Blazebit#414 - Implemented updatable entity views prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
beikov committed Nov 6, 2017
1 parent f66e881 commit 51d190f
Show file tree
Hide file tree
Showing 896 changed files with 55,517 additions and 4,242 deletions.
18 changes: 12 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ cache:
before_install:
- sh -c "if [ '$RDBMS' = 'firebird' ]; then sh travis/before_install_firebird.sh; fi"
install:
- sh -c "if [ '$JDK' = '9' ]; then sh travis/install_jdk9.sh; fi"
- sh -c "if [ '$LATEST_MAVEN' = 'true' ]; then sh travis/install_latest_maven.sh; fi"
before_script:
- sh -c "if [ '$JDK' = '9' ]; then sh travis/before_script_jdk9.sh; fi"
- sh -c "if [ '$RDBMS' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS test DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_bin;'; fi"
- sh -c "if [ '$RDBMS' = 'postgresql' ]; then psql -c 'create database test;' -U postgres; fi"
- sh -c "if [ '$RDBMS' = 'db2' ]; then sh travis/before_script_db2.sh; fi"
Expand Down Expand Up @@ -337,8 +335,16 @@ matrix:
# JDK 9
################################################
# JDK 9 - Not going to work until javassist is fixed
- env: JPAPROVIDER=hibernate-5.2 RDBMS=h2 JDK=9
sudo: true
- env: JPAPROVIDER=hibernate-5.2 RDBMS=h2 JDK=9 LATEST_MAVEN=true
addons:
apt:
packages:
- oracle-java9-installer
jdk: oraclejdk9
allow_failures:
- env: JPAPROVIDER=hibernate-5.2 RDBMS=h2 JDK=9
sudo: true
- env: JPAPROVIDER=hibernate-5.2 RDBMS=h2 JDK=9 LATEST_MAVEN=true
addons:
apt:
packages:
- oracle-java9-installer
jdk: oraclejdk9
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ The entity view itself is a simple interface describing the structure of the pro
```java
@EntityView(Cat.class)
public interface CatView {
@IdMapping("id")
@IdMapping
public Integer getId();

@Mapping("CONCAT(mother.name, 's kitty ', name)")
Expand All @@ -353,7 +353,7 @@ public interface CatView {
```java
@EntityView(Cat.class)
public interface SimpleCatView {
@IdMapping("id")
@IdMapping
public Integer getId();

public String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Cat.class)
public interface CatSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Person.class)
public interface PersonSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Cat.class)
public interface CatSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Person.class)
public interface PersonSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Cat.class)
public interface CatSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Person.class)
public interface PersonSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Cat.class)
public interface CatSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@EntityView(Person.class)
public interface PersonSimpleView {

@IdMapping("id")
@IdMapping
Long getId();

String getName();
Expand Down
6 changes: 2 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -e

if [ "$JDK" = "9" ]; then
MVN_BIN=/tmp/apache-maven/bin/mvn
export MAVEN_OPTS="-Xmx1024m -XX:MaxMetaspaceSize=512m --add-modules=java.se.ee"
export MAVEN_OPTS="-Xmx1024m -XX:MaxMetaspaceSize=512m" # --add-modules=java.se.ee"
elif [ "$LATEST_MAVEN" = "true" ]; then
MVN_BIN=/tmp/apache-maven/bin/mvn
export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=512m"
Expand All @@ -27,7 +27,7 @@ if [ "$TRAVIS_REPO_SLUG" == "Blazebit/blaze-persistence" ] &&
[ "$RDBMS" == "h2" ]; then
exec ${MVN_BIN} -P ${JPAPROVIDER},${RDBMS},${SPRING_DATA:-spring-data-1.11.x} install
else
if [ "$TRAVIS_REPO_SLUG" == "Blazebit/blaze-persistence" ] &&
if [ "$TRAVIS_REPO_SLUG" == "Blazebit/blaze-persistence" ] &&
[ "$TRAVIS_BRANCH" == "master" ] &&
[ "$TRAVIS_PULL_REQUEST" == "false" ] &&
[ "$JPAPROVIDER" == "hibernate-6.0" ] &&
Expand All @@ -41,5 +41,3 @@ else

eval exec ${MVN_BIN} -P ${JPAPROVIDER},${RDBMS},${SPRING_DATA:-spring-data-1.11.x} install --projects "core/testsuite,entity-view/testsuite,jpa-criteria/testsuite" -am $PROPERTIES
fi


Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
<property name="ignorePattern" value="@version|@see"/>
</module>
<module name="MethodLength">
<property name="max" value="200"/>
<property name="max" value="250"/>
</module>
<module name="ParameterNumber">
<property name="max" value="15"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

import com.blazebit.persistence.JoinType;

import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.EntityManager;
import javax.persistence.metamodel.EntityType;
import java.util.Map;

/**
* A JPA provider implementation provides information about which features are supported by a JPA implementation.
Expand Down Expand Up @@ -223,7 +224,7 @@ public interface JpaProvider {
* @param attributeName The attribute name to check
* @return True if join columns are in a foreign table, false otherwise
*/
public boolean isForeignJoinColumn(ManagedType<?> ownerType, String attributeName);
public boolean isForeignJoinColumn(EntityType<?> ownerType, String attributeName);

/**
* Whether columns for the given attribute are shared between multiple subtypes
Expand All @@ -233,7 +234,7 @@ public interface JpaProvider {
* @param attributeName The attribute name to check
* @return True if columns of the attribute are shared, false otherwise
*/
public boolean isColumnShared(ManagedType<?> ownerType, String attributeName);
public boolean isColumnShared(EntityType<?> ownerType, String attributeName);

/**
* Whether the association defined by owner type and attribute name, when treat joined requires a type filter to be applied via an ON
Expand All @@ -242,28 +243,62 @@ public interface JpaProvider {
* Hibernate for example does not automatically add the type constraint to treat joins of a type that is uses
* the table per class inheritance strategy.
*
* @param ownerType The type for which to check the treat filter requirement
* @param ownerType The declaring type of the attribute to check
* @param attributeName The attribute name for which to check the treat filter requirement or null
* @param joinType The join type used for the treat join
* @return True if a treat filter is required, false otherwise
*/
public ConstraintType requiresTreatFilter(ManagedType<?> ownerType, String attributeName, JoinType joinType);
public ConstraintType requiresTreatFilter(EntityType<?> ownerType, String attributeName, JoinType joinType);

/**
* Whether the given attribute is a collection that uses a join table.
* If the given attribute is an inverse collection, the mapped by attribute name is returned.
* Otherwise returns null.
*
* @param attribute The attribute to check
* @return True if uses a join table, false otherwise
* @param ownerType The declaring type of the attribute to check
* @param attributeName The name of the inverse attribute for which to retrieve the mapped by value
* @return The mapped by attribute name if the given attribute is an inverse collection, null otherwise
*/
public boolean isJoinTable(Attribute<?, ?> attribute);
public String getMappedBy(EntityType<?> ownerType, String attributeName);

/**
* If the given attribute is <em>insertable = false</em> and <em>updatable = false</em> it returns the writable mappings for the inverse type.
* Otherwise returns null.
*
* @param inverseType The type containing the inverse relation
* @param ownerType The declaring type of the attribute to check
* @param attributeName The name of the attribute for which to retrieve the writable mapped by mapping
* @return The writable mappings for the inverse type if the attribute is not insertable or updatable, null otherwise
*/
public Map<String, String> getWritableMappedByMappings(EntityType<?> inverseType, EntityType<?> ownerType, String attributeName);

/**
* If the given attribute is a collection that uses a join table, returns it's name.
* Otherwise returns null.
*
* @param ownerType The declaring type of the attribute to check
* @param attributeName The name of the attribute for which to retrieve the join table name
* @return The join table name if the attribute uses one, null otherwise
*/
public String getJoinTable(EntityType<?> ownerType, String attributeName);

/**
* Whether the given attribute is a non-indexed and non-ordered collection a.k.a. a bag.
*
* @param attribute The attribute to check
* @param ownerType The declaring type of the attribute to check
* @param attributeName The name of the attribute to check
* @return True if it is a bag, false otherwise
*/
public boolean isBag(Attribute<?, ?> attribute);
public boolean isBag(EntityType<?> ownerType, String attributeName);

/**
* Returns whether the entity with the id is contained in the entity managers persistence context.
*
* @param em The entity manager
* @param entityClass The entity class
* @param id The entity id
* @return True if it is contained, false otherwise
*/
public boolean containsEntity(EntityManager em, Class<?> entityClass, Object id);

/**
* Indicates if the provider supports expressions like
Expand All @@ -289,6 +324,14 @@ public interface JpaProvider {
*/
public boolean supportsForeignAssociationInOnClause();

/**
* Indicates whether an embeddable can be set via an update queries SET clause.
* Although the JPA spec mandates this, it doesn't seem to be asserted so some providers don't support it.
*
* @return true if supported, else false
*/
public boolean supportsUpdateSetEmbeddable();


/**
* Indicates if the provider supports the use of transient entity objects as parameters.
Expand Down Expand Up @@ -328,7 +371,6 @@ public interface JpaProvider {
* The possible locations of a constraint.
*
* @author Christian Beikov
* @since 1.2.0
*/
public static enum ConstraintType {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.blazebit.persistence.impl.query.CustomSQLQuery;
import com.blazebit.persistence.impl.query.EntityFunctionNode;
import com.blazebit.persistence.impl.query.QuerySpecification;
import com.blazebit.persistence.impl.util.JpaMetamodelUtils;
import com.blazebit.persistence.spi.DbmsStatementType;
import com.blazebit.persistence.spi.SetOperationType;

Expand Down Expand Up @@ -189,10 +190,10 @@ protected List<String> prepareAndGetAttributes() {
AttributePath attributePath = attributeColumnMappings.get(attributeName).getKey();
attributes.add(attributeName);

if (JpaUtils.isJoinable(attributePath.getAttributes().get(attributePath.getAttributes().size() - 1))) {
if (JpaMetamodelUtils.isJoinable(attributePath.getAttributes().get(attributePath.getAttributes().size() - 1))) {
// We have to map *-to-one relationships to their ids
EntityType<?> type = mainQuery.metamodel.entity(attributePath.getAttributeClass());
Attribute<?, ?> idAttribute = JpaUtils.getIdAttribute(type);
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getIdAttribute(type);
// NOTE: Since we are talking about *-to-ones, the expression can only be a path to an object
// so it is safe to just append the id to the path
Expression selectExpression = selectManager.getSelectInfos().get(bindingEntry.getValue()).getExpression();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.blazebit.persistence.ObjectBuilder;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.SelectObjectBuilder;
import com.blazebit.persistence.impl.util.JpaMetamodelUtils;

/**
*
Expand Down Expand Up @@ -132,8 +133,8 @@ private void checkEntityId(Object entityId) {
}

EntityType<?> entityType = mainQuery.metamodel.entity(joinManager.getRootNodeOrFail("Paginated queries do not support multiple from clause elements!").getType());
Attribute<?, ?> idAttribute = JpaUtils.getIdAttribute(entityType);
Class<?> idType = JpaUtils.resolveFieldClass(entityType.getJavaType(), idAttribute);
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getIdAttribute(entityType);
Class<?> idType = JpaMetamodelUtils.resolveFieldClass(entityType.getJavaType(), idAttribute);

if (!idType.isInstance(entityId)) {
throw new IllegalArgumentException("The type of the given entity id '" + entityId.getClass().getName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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.impl.util.JpaMetamodelUtils;
import com.blazebit.persistence.spi.DbmsModificationState;
import com.blazebit.persistence.spi.DbmsStatementType;

Expand Down Expand Up @@ -304,7 +305,7 @@ public <Z> TypedQuery<ReturningResult<Z>> getWithReturningQuery(String attribute
throw new IllegalArgumentException("Invalid empty attribute");
}

AttributePath attrPath = JpaUtils.getBasicAttributePath(getMetamodel(), entityType, attribute);
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 @@ -398,11 +399,11 @@ public SimpleReturningBuilder returning(String modificationQueryAttribute) {

if (isReturningEntityAliasAllowed && modificationQueryAttribute.equals(entityAlias)) {
// Our little special case, since there would be no other way to refer to the id as the object type
Attribute<?, ?> idAttribute = JpaUtils.getIdAttribute(entityType);
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getIdAttribute(entityType);
modificationQueryAttribute = idAttribute.getName();
}

List<Attribute<?, ?>> attributePath = JpaUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute).getAttributes();
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 @@ -438,10 +439,10 @@ public X returning(String cteAttribute, String modificationQueryAttribute) {
if (isReturningEntityAliasAllowed && modificationQueryAttribute.equals(entityAlias)) {
// Our little special case, since there would be no other way to refer to the id as the object type
queryAttrType = entityType.getJavaType();
Attribute<?, ?> idAttribute = JpaUtils.getIdAttribute(entityType);
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getIdAttribute(entityType);
modificationQueryAttribute = idAttribute.getName();
} else {
AttributePath queryAttributePath = JpaUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute);
AttributePath queryAttributePath = JpaMetamodelUtils.getBasicAttributePath(getMetamodel(), entityType, modificationQueryAttribute);
queryAttrType = queryAttributePath.getAttributeClass();
}

Expand Down Expand Up @@ -490,7 +491,7 @@ public CTEInfo createCTEInfo() {
throw new IllegalArgumentException("empty attribute at position " + i);
}

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

return attrs;
Expand Down Expand Up @@ -555,15 +556,15 @@ private TypedQuery<Object[]> getExampleQuery(List<List<Attribute<?, ?>>> attribu
}

// TODO: actually we should also check if the attribute is a @GeneratedValue
if (!dbmsDialect.supportsReturningColumns() && !JpaUtils.getIdAttribute(entityType).equals(lastPathElem)) {
if (!dbmsDialect.supportsReturningColumns() && !JpaMetamodelUtils.getIdAttribute(entityType).equals(lastPathElem)) {
throw new IllegalArgumentException("Returning the query attribute [" + lastPathElem.getName() + "] is not supported by the dbms, only generated keys can be returned!");
}

sb.append(entityAlias).append('.');
if (JpaUtils.isJoinable(lastPathElem)) {
if (JpaMetamodelUtils.isJoinable(lastPathElem)) {
// We have to map *-to-one relationships to their ids
EntityType<?> type = mainQuery.metamodel.entity(JpaUtils.resolveFieldClass(entityType.getJavaType(), lastPathElem));
Attribute<?, ?> idAttribute = JpaUtils.getIdAttribute(type);
EntityType<?> type = mainQuery.metamodel.entity(JpaMetamodelUtils.resolveFieldClass(entityType.getJavaType(), lastPathElem));
Attribute<?, ?> idAttribute = JpaMetamodelUtils.getIdAttribute(type);
// NOTE: Since we are talking about *-to-ones, the expression can only be a path to an object
// so it is safe to just append the id to the path
sb.append(lastPathElem.getName()).append('.').append(idAttribute.getName());
Expand Down
Loading

0 comments on commit 51d190f

Please sign in to comment.