Repository: deltaspike
Updated Branches:
  refs/heads/master eb58d604a -> 8df71b676


DELTASPIKE-1052 support named entity graphs

Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/8df71b67
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/8df71b67
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/8df71b67

Branch: refs/heads/master
Commit: 8df71b67611f4bc1b11272b1480631d874004a5b
Parents: eb58d60
Author: Harald Wellmann <[email protected]>
Authored: Tue Dec 29 18:27:09 2015 +0100
Committer: Harald Wellmann <[email protected]>
Committed: Tue Dec 29 18:28:11 2015 +0100

----------------------------------------------------------------------
 .../apache/deltaspike/data/api/EntityGraph.java |  35 ++++
 .../deltaspike/data/api/EntityGraphType.java    |  37 ++++
 .../data/impl/graph/EntityGraphException.java   |  36 ++++
 .../data/impl/graph/EntityGraphHelper.java      |  84 +++++++++
 .../impl/handler/CdiQueryInvocationContext.java |  37 +++-
 .../deltaspike/data/test/ee7/domain/Flat.java   |  74 ++++++++
 .../deltaspike/data/test/ee7/domain/Garage.java |  88 ++++++++++
 .../deltaspike/data/test/ee7/domain/House.java  |  97 +++++++++++
 .../deltaspike/data/test/ee7/domain/Tenant.java |  87 ++++++++++
 .../test/ee7/graph/HouseRepositoryTest.java     | 174 +++++++++++++++++++
 .../data/test/ee7/service/HouseRepository.java  |  48 +++++
 11 files changed, 788 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraph.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraph.java
 
b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraph.java
new file mode 100644
index 0000000..ec55532
--- /dev/null
+++ 
b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraph.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface EntityGraph
+{
+    String value() default "";
+    
+    EntityGraphType type() default EntityGraphType.FETCH;
+    
+    String[] paths() default { };
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraphType.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraphType.java
 
b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraphType.java
new file mode 100644
index 0000000..2f5364c
--- /dev/null
+++ 
b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityGraphType.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.api;
+
+public enum EntityGraphType
+{
+    FETCH("javax.persistence.fetchgraph"),
+    LOAD("javax.persistence.loadgraph");
+    
+    private String hintName;
+    
+    private EntityGraphType(String hintName)
+    {
+        this.hintName = hintName;
+    }
+    
+    public String getHintName()
+    {
+        return hintName;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphException.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphException.java
 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphException.java
new file mode 100644
index 0000000..4a3a4ca
--- /dev/null
+++ 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.impl.graph;
+
+public class EntityGraphException extends RuntimeException
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public EntityGraphException(String message)
+    {
+        super(message);
+    }
+
+    public EntityGraphException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphHelper.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphHelper.java
 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphHelper.java
new file mode 100644
index 0000000..72bad91
--- /dev/null
+++ 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/graph/EntityGraphHelper.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.impl.graph;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.persistence.EntityManager;
+
+import org.apache.deltaspike.core.util.ClassUtils;
+
+public final class EntityGraphHelper
+{
+
+    private static final Class<?> ENTITY_GRAPH_CLASS;
+
+    static
+    {
+        ENTITY_GRAPH_CLASS = 
ClassUtils.tryToLoadClassForName("javax.persistence.EntityGraph");
+    }
+    
+    
+    private EntityGraphHelper()
+    {
+        // hidden constructor
+    }
+
+    public static boolean isAvailable()
+    {
+        return ENTITY_GRAPH_CLASS != null;
+    }
+
+    public static Object getEntityGraph(EntityManager em, String graphName)
+    {
+        ensureAvailable();
+        try
+        {
+            Method method = EntityManager.class.getMethod("getEntityGraph", 
String.class);
+            return method.invoke(em, graphName);
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new EntityGraphException("no method 
EntityManager.getEntityGraph()", e);
+        }
+        catch (SecurityException e)
+        {
+            throw new EntityGraphException("no access to method 
EntityManager.getEntityGraph()", e);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new EntityGraphException("no access to method 
EntityManager.getEntityGraph()", e);
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new EntityGraphException(e.getCause().getMessage(), 
e.getCause());
+        }
+    }
+
+    private static void ensureAvailable()
+    {
+        if (!isAvailable())
+        {
+            throw new EntityGraphException(
+                "Class java.persistence.EntityGraph is not available. "
+                + "Does your PersistenceProvider support JPA 2.1?");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
index 2a19a40..f156741 100644
--- 
a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
+++ 
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
@@ -18,8 +18,20 @@
  */
 package org.apache.deltaspike.data.impl.handler;
 
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.LockModeType;
+import javax.persistence.Query;
+import javax.persistence.QueryHint;
+
+import org.apache.deltaspike.data.api.EntityGraph;
 import org.apache.deltaspike.data.api.SingleResultType;
 import org.apache.deltaspike.data.api.mapping.QueryInOutMapper;
+import org.apache.deltaspike.data.impl.graph.EntityGraphHelper;
 import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
 import org.apache.deltaspike.data.impl.param.Parameters;
 import org.apache.deltaspike.data.impl.property.Property;
@@ -27,15 +39,6 @@ import org.apache.deltaspike.data.impl.util.EntityUtils;
 import org.apache.deltaspike.data.impl.util.bean.Destroyable;
 import org.apache.deltaspike.data.spi.QueryInvocationContext;
 
-import javax.persistence.EntityManager;
-import javax.persistence.LockModeType;
-import javax.persistence.Query;
-import javax.persistence.QueryHint;
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.LinkedList;
-import java.util.List;
-
 public class CdiQueryInvocationContext implements QueryInvocationContext
 {
 
@@ -165,6 +168,7 @@ public class CdiQueryInvocationContext implements 
QueryInvocationContext
                 query.setHint(hint.name(), hint.value());
             }
         }
+        applyEntityGraph(query, method);
         query = applyJpaQueryPostProcessors(query);
         return query;
     }
@@ -309,6 +313,21 @@ public class CdiQueryInvocationContext implements 
QueryInvocationContext
     {
         return extractQueryHints(method) != null;
     }
+    
+    private void applyEntityGraph(Query query, Method method)
+    {
+        EntityGraph entityGraphAnn = method.getAnnotation(EntityGraph.class);
+        if (entityGraphAnn == null)
+        {
+            return;
+        }
+        
+        String graphName = entityGraphAnn.value();
+        Object graph = EntityGraphHelper.getEntityGraph(getEntityManager(), 
graphName);
+        query.setHint(entityGraphAnn.type().getHintName(), graph);
+    }
+
+    
 
     private boolean countCheck(Object entity)
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Flat.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Flat.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Flat.java
new file mode 100644
index 0000000..c961067
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Flat.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table
+public class Flat implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    @ManyToOne
+    private House house;
+
+    private String name;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public House getHouse()
+    {
+        return house;
+    }
+
+    public void setHouse(House house)
+    {
+        this.house = house;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Garage.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Garage.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Garage.java
new file mode 100644
index 0000000..7dd91dc
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Garage.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table
+public class Garage implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    private String name;
+
+    @ManyToOne
+    private House house;
+
+    @OneToOne(optional = true)
+    private Tenant tenant;
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public House getHouse()
+    {
+        return house;
+    }
+
+    public void setHouse(House house)
+    {
+        this.house = house;
+    }
+
+    public Tenant getTenant()
+    {
+        return tenant;
+    }
+
+    public void setTenant(Tenant tenant)
+    {
+        this.tenant = tenant;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/House.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/House.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/House.java
new file mode 100644
index 0000000..c8afcfd
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/House.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.domain;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.NamedAttributeNode;
+import javax.persistence.NamedEntityGraph;
+import javax.persistence.NamedEntityGraphs;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@NamedEntityGraphs({
+    @NamedEntityGraph(name = "withFlats", attributeNodes = 
@NamedAttributeNode("flats")),
+    @NamedEntityGraph(name = "withGarages", attributeNodes = 
@NamedAttributeNode("garages"))
+})
+@Entity
+@Table
+public class House implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    private String name;
+
+    @OneToMany(mappedBy = "house", cascade = CascadeType.ALL)
+    private List<Flat> flats = new ArrayList<Flat>();
+
+    @OneToMany(mappedBy = "house", cascade = CascadeType.ALL)
+    private List<Garage> garages = new ArrayList<Garage>();
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public List<Flat> getFlats()
+    {
+        return flats;
+    }
+
+    public void setFlats(List<Flat> flats)
+    {
+        this.flats = flats;
+    }
+
+    public List<Garage> getGarages()
+    {
+        return garages;
+    }
+
+    public void setGarages(List<Garage> garages)
+    {
+        this.garages = garages;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Tenant.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Tenant.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Tenant.java
new file mode 100644
index 0000000..fdab59c
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/domain/Tenant.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table
+public class Tenant implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    private String name;
+
+    @OneToOne(optional = true)
+    private Garage garage;
+
+    @OneToOne(optional = true)
+    private Flat flat;
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public Garage getGarage()
+    {
+        return garage;
+    }
+
+    public void setGarage(Garage garage)
+    {
+        this.garage = garage;
+    }
+
+    public Flat getFlat()
+    {
+        return flat;
+    }
+
+    public void setFlat(Flat flat)
+    {
+        this.flat = flat;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/graph/HouseRepositoryTest.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/graph/HouseRepositoryTest.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/graph/HouseRepositoryTest.java
new file mode 100644
index 0000000..8803300
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/graph/HouseRepositoryTest.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.graph;
+
+import static 
org.apache.deltaspike.data.test.ee7.util.TestDeployments.initDeployment;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceUnitUtil;
+import javax.transaction.UserTransaction;
+
+import org.apache.deltaspike.data.api.QueryInvocationException;
+import org.apache.deltaspike.data.impl.graph.EntityGraphException;
+import org.apache.deltaspike.data.test.ee7.domain.Flat;
+import org.apache.deltaspike.data.test.ee7.domain.Garage;
+import org.apache.deltaspike.data.test.ee7.domain.House;
+import org.apache.deltaspike.data.test.ee7.domain.Tenant;
+import org.apache.deltaspike.data.test.ee7.service.HouseRepository;
+import org.apache.deltaspike.test.category.WebEE7ProfileCategory;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+@Category(WebEE7ProfileCategory.class)
+@RunWith(Arquillian.class)
+public class HouseRepositoryTest
+{
+
+    public static String DS_PROPERTIES_WITH_ENV_AWARE_TX_STRATEGY = 
+        
"globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy="
+            + 
"org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy";
+
+    @Deployment
+    public static Archive<?> deployment()
+    {
+        return initDeployment()
+            .addClass(HouseRepository.class)
+            .addClasses(House.class, Flat.class, Garage.class, Tenant.class)
+            .addAsWebInfResource(new 
StringAsset(DS_PROPERTIES_WITH_ENV_AWARE_TX_STRATEGY),
+                "classes/META-INF/apache-deltaspike.properties");
+    }
+
+    @Inject
+    private HouseRepository repository;
+
+    @Inject
+    private UserTransaction tx;
+
+    @Produces
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    private PersistenceUnitUtil puu;
+
+    @Test
+    @InSequence(1)
+    public void should_run_modifying_in_transaction() throws Exception
+    {
+        House house = repository.findByName("Bellevue");
+        assertNotNull(house);
+        assertNotNull(house.getId());
+        assertEquals("Bellevue", house.getName());
+
+        assertTrue(puu.isLoaded(house, "flats"));
+        assertFalse(puu.isLoaded(house, "garages"));
+    }
+
+    @Test
+    @InSequence(2)
+    public void shouldNotLoadLazyAssociationsWithoutGraph() throws Exception
+    {
+        House house = repository.findOptionalByName("Bellevue");
+        assertNotNull(house);
+        assertNotNull(house.getId());
+        assertEquals("Bellevue", house.getName());
+
+        PersistenceUnitUtil puu = 
entityManager.getEntityManagerFactory().getPersistenceUnitUtil();
+
+        assertFalse(puu.isLoaded(house, "flats"));
+        assertFalse(puu.isLoaded(house, "garages"));
+    }
+
+    @Test
+    @InSequence(3)
+    public void should_combine_entity_graph_with_explicit_query() throws 
Exception
+    {
+        House house = repository.fetchByName("Bellevue");
+        assertNotNull(house);
+        assertNotNull(house.getId());
+        assertEquals("Bellevue", house.getName());
+
+        assertTrue(puu.isLoaded(house, "flats"));
+        assertFalse(puu.isLoaded(house, "garages"));
+    }
+
+    @Test
+    @InSequence(4)
+    public void should_throw_on_invalid_graph() throws Exception
+    {
+        try
+        {
+            repository.fetchByNameWithInvalidGraph("Bellevue");
+            fail("expected QueryInvocationException");
+        }
+        catch (QueryInvocationException e)
+        {
+            assertTrue(e.getCause() instanceof EntityGraphException);
+        }
+    }
+
+    @Before
+    public void init() throws Exception
+    {
+        puu = entityManager.getEntityManagerFactory().getPersistenceUnitUtil();
+        tx.begin();
+        if (repository.count() == 0)
+        {
+            House house = new House();
+            Flat flat1 = new Flat();
+            flat1.setName("Flat 1");
+            flat1.setHouse(house);
+
+            Flat flat2 = new Flat();
+            flat2.setName("Flat 2");
+            flat2.setHouse(house);
+
+            Garage garageA = new Garage();
+            garageA.setName("Garage A");
+            garageA.setHouse(house);
+
+            Garage garageB = new Garage();
+            garageB.setName("Garage B");
+            garageB.setHouse(house);
+
+            house.setName("Bellevue");
+            house.setFlats(Arrays.asList(flat1, flat2));
+            house.setGarages(Arrays.asList(garageA, garageB));
+
+            entityManager.persist(house);
+        }
+        tx.commit();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8df71b67/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/service/HouseRepository.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/service/HouseRepository.java
 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/service/HouseRepository.java
new file mode 100644
index 0000000..f9fa797
--- /dev/null
+++ 
b/deltaspike/modules/data/test-ee7/src/test/java/org/apache/deltaspike/data/test/ee7/service/HouseRepository.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.test.ee7.service;
+
+import org.apache.deltaspike.data.api.EntityGraph;
+import org.apache.deltaspike.data.api.FullEntityRepository;
+import org.apache.deltaspike.data.api.Modifying;
+import org.apache.deltaspike.data.api.Query;
+import org.apache.deltaspike.data.api.Repository;
+import org.apache.deltaspike.data.test.ee7.domain.House;
+
+@Repository
[email protected]
+public interface HouseRepository extends FullEntityRepository<House, Long>
+{
+    @EntityGraph("withFlats")
+    House findByName(String name);
+
+    House findOptionalByName(String name);
+    
+    @Query("select h from House h where h.name = ?1")
+    @EntityGraph("withFlats")
+    House fetchByName(String name);
+
+    @Query("select h from House h where h.name = ?1")
+    @EntityGraph("none")
+    House fetchByNameWithInvalidGraph(String name);
+
+    @Modifying @Query("delete from House")
+    int deleteAll();
+
+}

Reply via email to