This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch solomax/OPENJPA-2925 in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit 45baaf7a834e4f8edf903f3b38f98d55a27a1e09 Author: Maxim Solodovnik <solo...@apache.org> AuthorDate: Sun Feb 23 00:25:09 2025 +0700 [OPENJPA-2925] Tests for issue --- .../apache/openjpa/persistence/recursive/Cat.java | 75 +++++++++++++ .../openjpa/persistence/recursive/Human.java | 63 +++++++++++ .../TestRecursiveThenNonRecursiveRelationship.java | 82 +++++++++++++++ .../src/it/nonRecursiveRelations/pom.xml | 116 +++++++++++++++++++++ .../apache/openjpa/tools/maven/recursive/Cat.java | 77 ++++++++++++++ .../openjpa/tools/maven/recursive/Human.java | 65 ++++++++++++ .../src/main/resources/META-INF/persistence.xml | 37 +++++++ .../maven/test/NonRecursiveRelationsTest.java | 80 ++++++++++++++ 8 files changed, 595 insertions(+) diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Cat.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Cat.java new file mode 100644 index 000000000..6f43bccdf --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Cat.java @@ -0,0 +1,75 @@ +/* + * 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.openjpa.persistence.recursive; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +@Entity +public class Cat { + @Id + @GeneratedValue + private int id; + + @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER) + private List<Cat> children = new ArrayList<>(); + @ManyToOne + private Cat parent; + @ManyToOne + private Human human; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List<Cat> getChildren() { + return children; + } + + public void setChildren(List<Cat> children) { + this.children = children; + } + + public Cat getParent() { + return parent; + } + + public void setParent(Cat parent) { + this.parent = parent; + } + + public Human getHuman() { + return human; + } + + public void setHuman(Human human) { + this.human = human; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Human.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Human.java new file mode 100644 index 000000000..a3d0bc415 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/Human.java @@ -0,0 +1,63 @@ +/* + * 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.openjpa.persistence.recursive; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; + +@Entity +public class Human { + @Id + @GeneratedValue + private int id; + private String name; + + @OneToMany(mappedBy = "human", fetch = FetchType.EAGER) + private List<Cat> cats = new ArrayList<>(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public List<Cat> getCats() { + return cats; + } + + public void setCats(List<Cat> cats) { + this.cats = cats; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/TestRecursiveThenNonRecursiveRelationship.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/TestRecursiveThenNonRecursiveRelationship.java new file mode 100644 index 000000000..52274933e --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/recursive/TestRecursiveThenNonRecursiveRelationship.java @@ -0,0 +1,82 @@ +/* + * 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.openjpa.persistence.recursive; + +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +import jakarta.persistence.EntityManager; + +/** + * Test accessing a non-recursive relation of an instance that has been loaded via a recursive relation. + */ +public class TestRecursiveThenNonRecursiveRelationship extends SingleEMFTestCase { + @Override + public void setUp() { + setUp(DROP_TABLES, Cat.class, Human.class, + "openjpa.ConnectionFactoryProperties", "PrintParameters=True", + "openjpa.Log", "SQL=trace"); + } + + public void testRelationAccessedViaRecursiveRelationship() { + final String ALICE = "Alice"; + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + + Human alice = new Human(); + alice.setName(ALICE); + em.persist(alice); + Human bob = new Human(); + bob.setName("Bob"); + em.persist(bob); + + Cat parent = new Cat(); + parent.setHuman(alice); + em.persist(parent); + + Cat kitten1 = new Cat(); + kitten1.setParent(parent); + kitten1.setHuman(bob); + em.persist(kitten1); + + // Add a sibling that belongs to the same human so that later, when we are finding kitten1, parent will not be + // loaded directly, but instead via the path `kitten1.human.cats.parent`. Needed to reproduce + Cat kitten2 = new Cat(); + kitten2.setParent(parent); + kitten2.setHuman(bob); + em.persist(kitten2); + + em.getTransaction().commit(); + + int catId = parent.getId(); + int kitten1Id = kitten1.getId(); + + em.close(); + em = emf.createEntityManager(); + + Cat cat1 = em.find(Cat.class, catId); //comment this line to get an error + Cat jpqlKitten_1 = em.createQuery("SELECT c FROM Cat c WHERE c.id = :id", Cat.class) + .setParameter("id", kitten1Id) + .getSingleResult(); + Cat kitten_1 = em.find(Cat.class, kitten1Id); + assertEquals(ALICE, kitten_1.getParent().getHuman().getName()); + assertEquals(ALICE, jpqlKitten_1.getParent().getHuman().getName()); + + em.close(); + } +} diff --git a/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/pom.xml b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/pom.xml new file mode 100644 index 000000000..2b7e4b8d6 --- /dev/null +++ b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/pom.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<!-- + Maven release plugin requires the project tag to be on a single line. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + + <groupId>org.apache.openjpa.tools.openjpa-maven-plugin.testing</groupId> + <artifactId>modifyDatabase</artifactId> + <version>1.0-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.2</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-kernel</artifactId> + <version>@pom.version@</version> + </dependency> + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-jdbc</artifactId> + <version>@pom.version@</version> + </dependency> + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-persistence-jdbc</artifactId> + <version>@pom.version@</version> + </dependency> + + <dependency> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>@hsqldb.version@</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-dbcp2</artifactId> + <version>@dbcp2.version@</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.5.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-maven-plugin</artifactId> + <version>@pom.version@</version> + <configuration> + <includes>**/recursive/*.class</includes> + <addDefaultConstructor>true</addDefaultConstructor> + <enforcePropertyRestrictions>true</enforcePropertyRestrictions> + <persistenceXmlFile>${project.build.directory}/classes/META-INF/persistence.xml</persistenceXmlFile> + </configuration> + <executions> + <execution> + <id>enhancer</id> + <phase>process-classes</phase> + <goals> + <goal>enhance</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>@hsqldb.version@</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-dbcp2</artifactId> + <version>@dbcp2.version@</version> + </dependency> + </dependencies> + </plugin> + + </plugins> + </build> + +</project> diff --git a/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Cat.java b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Cat.java new file mode 100644 index 000000000..6ff2703e3 --- /dev/null +++ b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Cat.java @@ -0,0 +1,77 @@ +/* + * 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.openjpa.tools.maven.recursive; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +@Entity +@Table(name = "cat") +public class Cat { + @Id + @GeneratedValue + private int id; + + @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER) + private List<Cat> children = new ArrayList<>(); + @ManyToOne + private Cat parent; + @ManyToOne + private Human human; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List<Cat> getChildren() { + return children; + } + + public void setChildren(List<Cat> children) { + this.children = children; + } + + public Cat getParent() { + return parent; + } + + public void setParent(Cat parent) { + this.parent = parent; + } + + public Human getHuman() { + return human; + } + + public void setHuman(Human human) { + this.human = human; + } +} diff --git a/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Human.java b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Human.java new file mode 100644 index 000000000..c164a75de --- /dev/null +++ b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/java/org/apache/openjpa/tools/maven/recursive/Human.java @@ -0,0 +1,65 @@ +/* + * 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.openjpa.tools.maven.recursive; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +@Entity +@Table(name = "human") +public class Human { + @Id + @GeneratedValue + private int id; + private String name; + + @OneToMany(mappedBy = "human", fetch = FetchType.EAGER) + private List<Cat> cats = new ArrayList<>(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public List<Cat> getCats() { + return cats; + } + + public void setCats(List<Cat> cats) { + this.cats = cats; + } +} diff --git a/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/resources/META-INF/persistence.xml b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/resources/META-INF/persistence.xml new file mode 100644 index 000000000..b26215bf6 --- /dev/null +++ b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8" ?> + <!-- + 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. + --> + +<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence + https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"> + + <!-- simply all annotated persistent entities will be part of this unit--> + <persistence-unit name="TestUnit"> + <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> + <class>org.apache.openjpa.tools.maven.recursive.Cat</class> + <class>org.apache.openjpa.tools.maven.recursive.Human</class> + + <properties> + <property name="openjpa.RuntimeUnenhancedClasses" value="unsupported" /> + <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver" /> + <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:file:target/openjpa-hsqldb;hsqldb.lock_file=false" /> + <property name="openjpa.ConnectionUserName" value="SA" /> + <property name="openjpa.ConnectionPassword" value="" /> + <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" /> + <property name="openjpa.Log" value="DefaultLevel=TRACE, Tool=TRACE, SQL=TRACE" /> + </properties> + </persistence-unit> +</persistence> diff --git a/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/test/java/org/apache/openjpa/tools/maven/test/NonRecursiveRelationsTest.java b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/test/java/org/apache/openjpa/tools/maven/test/NonRecursiveRelationsTest.java new file mode 100644 index 000000000..c565722ed --- /dev/null +++ b/openjpa-tools/openjpa-maven-plugin/src/it/nonRecursiveRelations/src/test/java/org/apache/openjpa/tools/maven/test/NonRecursiveRelationsTest.java @@ -0,0 +1,80 @@ +/* + * 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.openjpa.tools.maven.test; + + +import org.junit.Test; +import static org.junit.Assert.*; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import org.apache.openjpa.tools.maven.recursive.Cat; +import org.apache.openjpa.tools.maven.recursive.Human; + +public class NonRecursiveRelationsTest { + @Test + public void testRelationAccessedViaRecursiveRelationship() { + final String ALICE = "Alice"; + EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestUnit"); + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + + Human alice = new Human(); + alice.setName(ALICE); + em.persist(alice); + Human bob = new Human(); + bob.setName("Bob"); + em.persist(bob); + + Cat parent = new Cat(); + parent.setHuman(alice); + em.persist(parent); + + Cat kitten1 = new Cat(); + kitten1.setParent(parent); + kitten1.setHuman(bob); + em.persist(kitten1); + + // Add a sibling that belongs to the same human so that later, when we are finding kitten1, parent will not be + // loaded directly, but instead via the path `kitten1.human.cats.parent`. Needed to reproduce + Cat kitten2 = new Cat(); + kitten2.setParent(parent); + kitten2.setHuman(bob); + em.persist(kitten2); + + em.getTransaction().commit(); + + int catId = parent.getId(); + int kitten1Id = kitten1.getId(); + + em.close(); + em = emf.createEntityManager(); + + Cat cat1 = em.find(Cat.class, catId); //comment this line to get an error + Cat jpqlKitten_1 = em.createQuery("SELECT c FROM Cat c WHERE c.id = :id", Cat.class) + .setParameter("id", kitten1Id) + .getSingleResult(); + Cat kitten_1 = em.find(Cat.class, kitten1Id); + assertEquals(ALICE, kitten_1.getParent().getHuman().getName()); + assertEquals(ALICE, jpqlKitten_1.getParent().getHuman().getName()); + + em.close(); + } +}