[hibernate-commits] Hibernate SVN: r10283 - in trunk/HibernateExt/metadata: lib src/java/org/hibernate/cfg src/java/org/hibernate/cfg/annotations src/test/org/hibernate/test/annotations src/test/org/hibernate/test/annotations/idmanytoone

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Aug 18 15:53:45 EDT 2006


Author: epbernard
Date: 2006-08-18 15:53:41 -0400 (Fri, 18 Aug 2006)
New Revision: 10283

Added:
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Card.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardField.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardKey.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/IdManyToOne.java
   trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Project.java
Modified:
   trunk/HibernateExt/metadata/lib/ejb3-persistence.jar
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/FkSecondPass.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java
   trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java
Log:
ANN-382 Order FK setup to make it handle all non circular graphs

Modified: trunk/HibernateExt/metadata/lib/ejb3-persistence.jar
===================================================================
(Binary files differ)

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -1754,7 +1754,7 @@
 		mappings.addSecondPass(
 				new FkSecondPass(
 						value, columns,
-						!optional && unique, //cannot have nullabe and unique on certain DBs
+						!optional && unique, //cannot have nullabe and unique on certain DBs like Derby
 						path, mappings
 				)
 		);

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -278,20 +278,11 @@
 		}
 		caches.clear();
 
-		log.debug( "processing manytoone fk mappings" );
+		processFkSecondPassInOrder();
 		Iterator iter = secondPasses.iterator();
 		while ( iter.hasNext() ) {
 			SecondPass sp = (SecondPass) iter.next();
 			//do the second pass of fk before the others and remove them
-			if ( sp instanceof FkSecondPass ) {
-				sp.doSecondPass( classes ); 
-				iter.remove();
-			}
-		}
-		iter = secondPasses.iterator();
-		while ( iter.hasNext() ) {
-			SecondPass sp = (SecondPass) iter.next();
-			//do the second pass of fk before the others and remove them
 			if ( sp instanceof CreateKeySecondPass ) {
 				sp.doSecondPass( classes ); 
 				iter.remove();
@@ -330,6 +321,68 @@
 		}
 	}
 
+	private void processFkSecondPassInOrder() {
+		log.debug( "processing manytoone fk mappings" );
+		Iterator iter = secondPasses.iterator();
+		/* We need to process FKSecond pass trying to resolve any
+		 * graph circularity (ie PK made of a many to one linking to
+		 * an entity having a PK made of a ManyToOne ...
+		 */
+		Set fkSecondPasses = new HashSet();
+		while ( iter.hasNext() ) {
+			SecondPass sp = (SecondPass) iter.next();
+			//do the second pass of fk before the others and remove them
+			if ( sp instanceof FkSecondPass ) {
+				fkSecondPasses.add(sp);
+				iter.remove();
+			}
+		}
+		if (fkSecondPasses.size() > 0) {
+			Map<String, Set<String>> isADependencyOf = new HashMap<String, Set<String>>();
+			List orderedFkSecondPasses = new ArrayList( fkSecondPasses.size() );
+			List orderedTable = new ArrayList( fkSecondPasses.size() );
+			Iterator it = fkSecondPasses.iterator();
+			while ( it.hasNext() ) {
+				FkSecondPass sp = (FkSecondPass) it.next();
+				String referenceEntityName = sp.getValue().getReferencedEntityName();
+				String dependentTable = getClassMapping( referenceEntityName ).getTable().getQuotedName();
+				if ( ! isADependencyOf.containsKey( dependentTable ) ) {
+					isADependencyOf.put( dependentTable, new HashSet<String>() );
+				}
+				String table = sp.getValue().getTable().getQuotedName();
+				isADependencyOf.get( dependentTable ).add( table );
+				int beAfter = orderedTable.indexOf( dependentTable );
+				int beBefore = orderedFkSecondPasses.size();
+				Set<String> dependencies = isADependencyOf.get( table );
+				if (dependencies != null) {
+					for ( String tableDep : dependencies ) {
+						//for each declared dependency take the lowest index
+						int index = orderedTable.indexOf( tableDep );
+						//index = -1 when we have a self dependency
+						beBefore = index != -1 && index < beBefore ? index : beBefore;
+					}
+				}
+				int currentIndex = orderedTable.indexOf( table );
+				if (beBefore < beAfter ||
+						(currentIndex != -1 && ( currentIndex < beAfter || currentIndex > beBefore ) )
+						) {
+					StringBuilder sb = new StringBuilder("Foreign key circularity dependency involving the following tables: ");
+					sb.append( table );
+					if (beAfter > -1) sb.append(", ").append( dependentTable );
+					if ( beBefore < orderedFkSecondPasses.size() ) sb.append(", ").append( orderedTable.get(beBefore) );
+					throw new AnnotationException( sb.toString() );
+				}
+				currentIndex = currentIndex == -1 ? beBefore : currentIndex;
+				orderedTable.add( currentIndex, table );
+				orderedFkSecondPasses.add( currentIndex, sp );
+			}
+			it = orderedFkSecondPasses.listIterator();
+			while ( it.hasNext() ) {
+				( (SecondPass) it.next() ).doSecondPass( classes );
+			}
+		}
+	}
+
 	private void processArtifactsOfType(String artifact) {
 		if ( "hbm".equalsIgnoreCase( artifact ) ) {
 			log.debug( "Process hbm files" );

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/FkSecondPass.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/FkSecondPass.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/FkSecondPass.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -8,7 +8,7 @@
 import org.hibernate.mapping.ManyToOne;
 import org.hibernate.mapping.OneToOne;
 import org.hibernate.mapping.PersistentClass;
-import org.hibernate.mapping.Value;
+import org.hibernate.mapping.ToOne;
 
 /**
  * Enable a proper set of the FK columns in respect with the id column order
@@ -18,13 +18,13 @@
  * @author Emmanuel Bernard
  */
 public class FkSecondPass implements SecondPass {
-	private Value value;
+	private ToOne value;
 	private Ejb3JoinColumn[] columns;
 	private boolean unique;
 	private ExtendedMappings mappings;
 	private String path;
 
-	FkSecondPass(Value value, Ejb3JoinColumn[] columns, boolean unique, String path, ExtendedMappings mappings) {
+	FkSecondPass(ToOne value, Ejb3JoinColumn[] columns, boolean unique, String path, ExtendedMappings mappings) {
 		this.mappings = mappings;
 		this.value = value;
 		this.columns = columns;
@@ -32,6 +32,10 @@
 		this.path = path;
 	}
 
+	public ToOne getValue() {
+		return value;
+	}
+
 	public void doSecondPass(java.util.Map persistentClasses) throws MappingException {
 		if ( value instanceof ManyToOne ) {
 			ManyToOne manyToOne = (ManyToOne) value;

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -293,7 +293,7 @@
 								break;
 							}
 						}
-						if ( match == false ) {
+						if ( !match ) {
 							throw new AnnotationException(
 									"Column name " + col.getName() + " of "
 											+ referencedEntity.getEntityName() + " not found in JoinColumns.referencedColumnName"

Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -8,7 +8,7 @@
  * @author Emmanuel Bernard
  */
 public class Version {
-	public static String VERSION = "3.2.0.CR1";
+	public static String VERSION = "3.2.0.CR2";
 	private static Log log = LogFactory.getLog( Version.class );
 
 	static {

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Card.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Card.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Card.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -0,0 +1,29 @@
+//$Id: $
+package org.hibernate.test.annotations.idmanytoone;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Embeddable;
+import javax.persistence.ManyToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Card {
+
+	@Id
+	private CardPrimaryKey primaryKey = new CardPrimaryKey();
+
+	@Embeddable
+	private class CardPrimaryKey implements Serializable {
+
+		@ManyToOne(optional = false)
+		private Project project;
+
+		//An other @ManyToOne is also present in the real model
+		//The problem still occurs even when i remove this relation, it was no use to kept it for describe the problem
+
+	}
+}

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardField.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardField.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardField.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -0,0 +1,32 @@
+//$Id: $
+package org.hibernate.test.annotations.idmanytoone;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Embeddable;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class CardField {
+
+	@Id
+	private PrimaryKey primaryKey = new PrimaryKey();
+
+	@ManyToOne
+	private Card cardtmp;
+
+	@Embeddable
+	private class PrimaryKey implements Serializable {
+
+		@ManyToOne(optional = false)
+		private Card card;
+
+		@ManyToOne(optional = false)
+		private CardKey key;
+	}
+}
+

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardKey.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardKey.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/CardKey.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -0,0 +1,16 @@
+//$Id: $
+package org.hibernate.test.annotations.idmanytoone;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class CardKey {
+	@Id
+	@GeneratedValue
+	private int id;
+}

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/IdManyToOne.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/IdManyToOne.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/IdManyToOne.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -0,0 +1,25 @@
+//$Id: $
+package org.hibernate.test.annotations.idmanytoone;
+
+import org.hibernate.Session;
+import org.hibernate.test.annotations.TestCase;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class IdManyToOne extends TestCase {
+	public void testFkCreationOrdering() throws Exception {
+		//no real test case, the sessionFactory building is tested
+		Session s = openSession();
+		s.close();
+	}
+
+	protected Class[] getMappings() {
+		return new Class[] {
+				CardKey.class,
+				CardField.class,
+				Card.class,
+				Project.class
+		};
+	}
+}

Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Project.java
===================================================================
--- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Project.java	2006-08-18 15:17:00 UTC (rev 10282)
+++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/idmanytoone/Project.java	2006-08-18 19:53:41 UTC (rev 10283)
@@ -0,0 +1,17 @@
+//$Id: $
+package org.hibernate.test.annotations.idmanytoone;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Project {
+
+	@Id
+	@GeneratedValue
+	private int id;
+}




More information about the hibernate-commits mailing list