You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mi...@apache.org on 2009/12/17 02:29:13 UTC

svn commit: r891509 - in /openjpa/branches/1.3.x: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/

Author: mikedd
Date: Thu Dec 17 01:29:12 2009
New Revision: 891509

URL: http://svn.apache.org/viewvc?rev=891509&view=rev
Log:
OPENJPA-1397:
Allow some columns of compound keys to be null.
Merged from trunk commit by Pinaki Poddar.
Testcase Submitted By: Michael Vorburger.

Added:
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java   (with props)
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java   (with props)
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java   (with props)
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java   (with props)
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java   (with props)
    openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java   (with props)
Modified:
    openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java

Modified: openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=891509&r1=891508&r2=891509&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Thu Dec 17 01:29:12 2009
@@ -171,6 +171,7 @@
         FieldMapping fm;
         Joinable join;
         int pkIdx;
+        boolean isNullPK = true;
         boolean canReadDiscriminator = true;
         for (int i = 0; i < pks.length; i++) {
             // we know that all pk column join mappings use primary key fields,
@@ -186,10 +187,12 @@
                 vals[pkIdx] = join.getPrimaryKeyValue(res, join.getColumns(),
                     fk, store, joins);
                 res.endDataRequest();
-                if (vals[pkIdx] == null)
-                    return null;
+                isNullPK = isNullPK && vals[pkIdx] == null;
             }
         }
+        if (isNullPK) {
+            return null;
+        }
 
         // the oid data is loaded by the base type, but if discriminator data
         // is present, make sure to use it to construct the actual oid instance

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,56 @@
+/*
+ * 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.identity;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * JPA Entity with a compound Id of two fields, one simple and one an Entity.
+ */
+@Entity
+@Table(name = "test_complex")
+@IdClass(ComplexCompoundIdTestEntityId.class)
+public class ComplexCompoundIdTestEntity {
+
+	@Id
+	@Column(nullable = false)
+	private Long id;
+
+    @Id
+    @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, 
+            fetch = FetchType.LAZY, optional = true)
+    @JoinColumn(nullable = true, name = "type_id")
+	private TypeEntity type;
+
+	public Long getId() {
+		return id;
+	}
+
+	public TypeEntity getType() {
+		return type;
+	}
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,61 @@
+/*
+ * 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.identity;
+
+
+/**
+ * JPA Id for ComplexCompoundIdTestEntity.
+ */
+public class ComplexCompoundIdTestEntityId {
+
+	private Long id;
+
+	private Long type;
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		result = prime * result + ((type == null) ? 0 : type.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		ComplexCompoundIdTestEntityId other = (ComplexCompoundIdTestEntityId) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		if (type == null) {
+			if (other.type != null)
+				return false;
+		} else if (!type.equals(other.type))
+			return false;
+		return true;
+	}
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/ComplexCompoundIdTestEntityId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,54 @@
+/*
+ * 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.identity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+/**
+ * JPA Entity with a compound Id of two fields, both simple.
+ */
+@Entity
+@Table(name = "test_simple")
+@IdClass(SimpleCompoundIdTestEntityId.class)
+public class SimpleCompoundIdTestEntity {
+
+	@Id
+	@Column(nullable = false)
+	private Long firstId;
+
+	@Id
+	@Column(nullable = true)
+	private Long secondId;
+
+	// ...
+	
+	public Long getFirstId() {
+		return firstId;
+	}
+
+	public Long getSecondId() {
+		return secondId;
+	}
+	
+	// ...
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,62 @@
+/*
+ * 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.identity;
+
+
+/**
+ * JPA Id for SimpleCompoundIdTestEntity.
+ */
+public class SimpleCompoundIdTestEntityId {
+
+	public Long firstId;
+
+	public Long secondId;
+
+	
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((firstId == null) ? 0 : firstId.hashCode());
+		result = prime * result + ((secondId == null) ? 0 : secondId.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		SimpleCompoundIdTestEntityId other = (SimpleCompoundIdTestEntityId) obj;
+		if (firstId == null) {
+			if (other.firstId != null)
+				return false;
+		} else if (!firstId.equals(other.firstId))
+			return false;
+		if (secondId == null) {
+			if (other.secondId != null)
+				return false;
+		} else if (!secondId.equals(other.secondId))
+			return false;
+		return true;
+	}
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/SimpleCompoundIdTestEntityId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.identity;
+
+import java.sql.Connection;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Test that compound identity can consists of null component column value.
+ * 
+ * This test uses pre-defined database tables created by DDL explicitly.
+ * The tables have <em>logical</em> compound primary keys in the sense non-null
+ * constraint is <em>not</em> set on the primary columns. The tables are populated 
+ * with SQL to contain null values in these columns. 
+ * The test verifies that results are returned as par expectation.
+ * For more details, refer
+ * <A href="https://issues.apache.org/jira/browse/OPENJPA-1397">JIRA-1397</A>
+ */
+public class TestCompundIdWithNull extends SingleEMFTestCase {
+    private static boolean tablesCreated = false;
+	public void setUp() throws Exception {
+	    // do not use CLEAR_TABLES or DROP_TABLES
+	    super.setUp(SimpleCompoundIdTestEntity.class, ComplexCompoundIdTestEntity.class, TypeEntity.class);
+	    if (!tablesCreated) {
+	        createTables(emf.createEntityManager());
+	    }
+	    
+	}
+	
+	public void testSimpleCompoundIdTestEntity() throws Exception  {
+			EntityManager em = emf.createEntityManager();
+			String jpql = "SELECT o FROM SimpleCompoundIdTestEntity o ORDER BY o.secondId";
+			List list = em.createQuery(jpql).getResultList();
+			assertEquals(2, list.size());
+			assertEquals(Long.valueOf(123), ((SimpleCompoundIdTestEntity) list.get(0)).getSecondId());
+			
+			SimpleCompoundIdTestEntity secondResult = (SimpleCompoundIdTestEntity) list.get(1);
+			assertNotNull("BUG (JIRA-1397)! Result list contains null in second element", secondResult);
+			assertNull(secondResult.getSecondId());
+			em.close();
+	}
+
+	
+	public void testComplexCompoundIdTestEntity() throws Exception  {
+			EntityManager em = emf.createEntityManager();
+			String jpql = "SELECT o FROM ComplexCompoundIdTestEntity o ORDER BY o.type";
+			List list = em.createQuery(jpql).getResultList();
+			assertEquals(2, list.size());
+			ComplexCompoundIdTestEntity secondResult = (ComplexCompoundIdTestEntity) list.get(1);
+			assertNotNull("Result list contains null in second element", secondResult);
+			assertNull("Result list's second record secondId field was not null", secondResult.getType());
+			em.close();
+	}
+	
+	/**
+	 * Create tables with logical compound keys without non-null constraint.
+	 * Populate them with null values in some of the columns.
+	 */
+    private void createTables(EntityManager em) throws Exception {
+        em.getTransaction().begin();
+        OpenJPAEntityManager kem = OpenJPAPersistence.cast(em);
+
+        Connection conn = (Connection) kem.getConnection();
+        // NOTE that 'logically' test_simple has a ", CONSTRAINT test_simple_pk PRIMARY KEY (firstId, secondId)",
+        // but at least Derby doesn't permit NULL then.. in our real-world underlying schema that leads
+        // to this there are *NO* PRIMARY KEY on any tables, but there is a logical model expressed
+        // elsewhere stating that those two columns uniquely identify a row.
+        try {
+            conn.createStatement().execute("DROP TABLE test_type");
+            conn.createStatement().execute("DROP TABLE test_simple");
+            conn.createStatement().execute("DROP TABLE test_complex");
+        } catch (Exception e) {
+        }
+        
+        conn.createStatement().execute("CREATE TABLE test_simple(firstId NUMERIC, secondId NUMERIC)");
+        conn.createStatement().execute("INSERT INTO test_simple(firstId, secondId) VALUES (1, 123)");
+        conn.createStatement().execute("INSERT INTO test_simple(firstId, secondId) VALUES (1, NULL)");
+
+        conn.createStatement().execute("CREATE TABLE test_type(id NUMERIC CONSTRAINT test_type_pk PRIMARY KEY, " +
+                "code VARCHAR(16))");
+        conn.createStatement().execute("INSERT INTO test_type(id, code) VALUES (987, 'ABC')");
+
+        conn.createStatement().execute("CREATE TABLE test_complex(id NUMERIC, type_id NUMERIC)");
+        conn.createStatement().execute("INSERT INTO test_complex(id, type_id) VALUES (1, 987)");
+        conn.createStatement().execute("INSERT INTO test_complex(id, type_id) VALUES (1, NULL)");
+
+        conn.close();
+        
+        em.flush();
+        em.getTransaction().commit();
+        em.close();
+    }
+	    
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TestCompundIdWithNull.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java?rev=891509&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java Thu Dec 17 01:29:12 2009
@@ -0,0 +1,20 @@
+package org.apache.openjpa.persistence.identity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * JPA Entity
+ */
+@Entity
+@Table(name = "test_type")
+public class TypeEntity {
+
+	@Id
+	private Long id;
+	
+	private String code;
+	
+	// ...
+}

Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/identity/TypeEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native