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(); + +}
