Author: max.andersen(a)jboss.com
Date: 2007-11-04 10:40:50 -0500 (Sun, 04 Nov 2007)
New Revision: 14188
Added:
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/CompositeIdJPATest.java
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/ManyToManyJDK50Test.java
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCBinder.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/JDBCReader.java
branches/Branch_3_2/HibernateExt/tools/src/test/org/hibernate/tool/BaseTestCase.java
Log:
HBX-755 incorrect genreated code for many-to-many relationship
+ referencecolumns for existing foreignkeys are now also collected (before just user
provided fk's had that)
HBX-846 Needed a method that finds Table by TableIdentifier (via runtimeInfo.getTable())
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCBinder.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCBinder.java 2007-11-04
08:54:31 UTC (rev 14187)
+++
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCBinder.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -303,6 +303,7 @@
}
SimpleValue keyValue = new DependantValue( collectionTable, referencedKeyValue );
+ //keyValue.setForeignKeyName("none"); // Avoid creating the foreignkey
//key.setCascadeDeleteEnabled( "cascade".equals(
subnode.attributeValue("on-delete") ) );
Iterator columnIterator = foreignKey.getColumnIterator();
while ( columnIterator.hasNext() ) {
@@ -932,6 +933,22 @@
public void secondPass(Map persistentClasses, Map inheritedMetas) throws
MappingException {
JDBCBinder.bindCollectionSecondPass(collection, persistentClasses, mappings,
inheritedMetas);
}
+
+ public void doSecondPass(Map persistentClasses) throws MappingException {
+ Value element = collection.getElement();
+ DependantValue dep = null;
+ String oldFkName = null;
+ if(element instanceof DependantValue) {
+ dep = (DependantValue)element;
+ oldFkName = dep.getForeignKeyName();
+ dep.setForeignKeyName("none"); // Workaround to avoid DependantValue
to create foreignkey just because reference columns are not the same + no need to create
keys already in the db!
+ }
+ super.doSecondPass(persistentClasses);
+ if(dep!=null) {
+ dep.setForeignKeyName(oldFkName);
+ }
+
+ }
}
}
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java 2007-11-04
08:54:31 UTC (rev 14187)
+++
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -30,10 +30,12 @@
protected void secondPassCompileForeignKeys(Table table, Set done)
throws MappingException {
- //super.secondPassCompileForeignKeys(table, done);
+ super.secondPassCompileForeignKeys(table, done);
// TODO: doing nothing to avoid creating foreignkeys which is NOT actually in the
database.
}
+
+
public void readFromJDBC() {
JDBCBinder binder = new JDBCBinder(this, buildSettings(),
createMappings(),revEngStrategy);
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java 2007-11-04
08:54:31 UTC (rev 14187)
+++
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -164,7 +164,7 @@
}
public void close() {
- runtimeInfo = null;
+
}
@@ -203,6 +203,21 @@
}
public boolean isForeignKeyCollectionInverse(String name, TableIdentifier
foreignKeyTable, List columns, TableIdentifier foreignKeyReferencedTable, List
referencedColumns) {
+ Table fkTable = getRuntimeInfo().getTable(foreignKeyTable);
+ if(fkTable==null) {
+ return true; // we don't know better
+ }
+
+ if(isManyToManyTable(fkTable)) {
+ // if the reference column is the first one then we are inverse.
+ Column column = fkTable.getColumn(0);
+ Column fkColumn = (Column) referencedColumns.get(0);
+ if(fkColumn.equals(column)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
return true;
}
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/JDBCReader.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/JDBCReader.java 2007-11-04
08:54:31 UTC (rev 14187)
+++
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/cfg/reveng/JDBCReader.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -190,7 +190,7 @@
String fkSchema = getSchemaForModel((String)
exportedKeyRs.get("FKTABLE_SCHEM"));
String fkTableName = (String) exportedKeyRs.get("FKTABLE_NAME");
String fkColumnName = (String) exportedKeyRs.get("FKCOLUMN_NAME");
- //String pkColumnName = (String) exportedKeyRs.get("PKCOLUMN_NAME");
+ String pkColumnName = (String) exportedKeyRs.get("PKCOLUMN_NAME");
String fkName = (String) exportedKeyRs.get("FK_NAME");
short keySeq = ((Short)exportedKeyRs.get("KEY_SEQ")).shortValue();
@@ -235,6 +235,19 @@
column = existingColumn==null ? column : existingColumn;
depColumns.add(column);
+
+ List primColumns = (List) referencedColumns.get(fkName);
+ if (primColumns == null) {
+ primColumns = new ArrayList();
+ referencedColumns.put(fkName,primColumns);
+ }
+
+ Column refColumn = new Column(pkColumnName);
+ existingColumn = referencedTable.getColumn(refColumn);
+ refColumn = existingColumn==null?refColumn:existingColumn;
+
+ primColumns.add(refColumn);
+
}
}
finally {
Modified:
branches/Branch_3_2/HibernateExt/tools/src/test/org/hibernate/tool/BaseTestCase.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/test/org/hibernate/tool/BaseTestCase.java 2007-11-04
08:54:31 UTC (rev 14187)
+++
branches/Branch_3_2/HibernateExt/tools/src/test/org/hibernate/tool/BaseTestCase.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -30,7 +30,7 @@
public abstract class BaseTestCase extends TestCase {
- protected static abstract class ExecuteContext {
+ public static abstract class ExecuteContext {
private final File sourceDir;
private final File outputDir;
Added:
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/CompositeIdJPATest.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/CompositeIdJPATest.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/CompositeIdJPATest.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -0,0 +1,154 @@
+/*
+ * Created on 13-Jan-2005
+ *
+ */
+package org.hibernate.tool.test.jdbc2cfg;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.cfg.JDBCMetaDataConfiguration;
+import org.hibernate.mapping.ForeignKey;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.Table;
+import org.hibernate.tool.JDBCMetaDataBinderTestCase;
+import org.hibernate.tool.hbm2x.Cfg2JavaTool;
+import org.hibernate.tool.hbm2x.POJOExporter;
+import org.hibernate.tool.hbm2x.pojo.EntityPOJOClass;
+
+/**
+ * @author max
+ *
+ */
+public class CompositeIdJPATest extends JDBCMetaDataBinderTestCase {
+
+
+ protected void configure(JDBCMetaDataConfiguration configuration) {
+ super.configure( configuration );
+ }
+ protected String[] getCreateSQL() {
+
+ return new String[] {
+ "CREATE TABLE Person ( id identity, name varchar(100) NOT NULL, address
varchar(255), city varchar(20) default NULL, PRIMARY KEY (id))"
+ ,
+ "create table modelyear ( make varchar(20), model varchar(30), year int,
name varchar(30), primary key (make, model, year))",
+ "CREATE TABLE Vehicle ( " +
+ " state varchar(2) NOT NULL, " +
+ " registration varchar(8) NOT NULL, " +
+ " v_make varchar(20) , " +
+ " v_model varchar(30) , " +
+ " v_year int , " +
+ " owner int , " +
+ " PRIMARY KEY (registration), " +
+ //" KEY (make,model,year), " +
+ //" KEY (owner), " +
+ " constraint vehicle_owner FOREIGN KEY (owner) REFERENCES person
(id), " +
+ " constraint vehicle_modelyear FOREIGN KEY (v_make, v_model,
v_year) REFERENCES modelyear (make, model, year) " +
+ " )" ,
+ };
+ }
+
+ protected String[] getDropSQL() {
+ return new String[] {
+ "drop table Vehicle",
+ "drop table modelyear",
+ "drop table Person",
+
+
+ };
+ }
+
+ public void testMultiColumnForeignKeys() {
+
+ Table vehicleTable = getTable(identifier("Vehicle"));
+
+ Iterator foreignKeyIterator = vehicleTable.getForeignKeyIterator();
+ assertHasNext(2, foreignKeyIterator);
+
+ ForeignKey foreignKey = getForeignKey(vehicleTable,
identifier("vehicle_owner"));
+ assertEquals(foreignKey.getColumnSpan(), 1);
+
+ foreignKey = getForeignKey(vehicleTable,
identifier("vehicle_modelyear"));
+ assertEquals(foreignKey.getColumnSpan(), 3);
+
+ PersistentClass vehicle = getConfiguration().getClassMapping("Vehicle");
+ EntityPOJOClass vechiclePojo = new EntityPOJOClass(vehicle, new Cfg2JavaTool());
+ assertNotNull(vechiclePojo.getDecoratedObject());
+
+ Property property = vehicle.getProperty("modelyear");
+ assertNotNull(property);
+ String generateJoinColumnsAnnotation =
vechiclePojo.generateJoinColumnsAnnotation(property, cfg);
+
assertTrue(generateJoinColumnsAnnotation.indexOf("referencedColumnName=\"MAKE\"")>0);
+
+
+ }
+
+ public void testJPAGeneration() throws Exception {
+ getConfiguration().buildMappings();
+ POJOExporter exporter = new POJOExporter(getConfiguration(), getOutputDir());
+ Properties p = new Properties();
+ p.setProperty("jdk5", "true");
+ p.setProperty("ejb3", "true");
+
+ exporter.setProperties(p);
+ exporter.start();
+
+ File file = new File( "ejb3compilable" );
+ file.mkdir();
+
+ ArrayList list = new ArrayList();
+ List jars = new ArrayList();
+ addAnnotationJars(jars);
+
+ new ExecuteContext(getOutputDir(), file, jars) {
+
+ protected void execute() throws Exception {
+ AnnotationConfiguration configuration = new AnnotationConfiguration();
+ configuration.addAnnotatedClass( getUcl().loadClass( "Vehicle" ) );
+ configuration.addAnnotatedClass( getUcl().loadClass( "Person" ) );
+ configuration.addAnnotatedClass( getUcl().loadClass( "Modelyear" ) );
+
+ SessionFactory sf = configuration.buildSessionFactory();
+ Session s = sf.openSession();
+ Query createQuery = s.createQuery("from java.lang.Object");
+ createQuery.list();
+ s.close();
+ sf.close();
+
+ }
+
+ }.run();
+ }
+
+ private void addAnnotationJars(List jars) {
+ jars.add( "ejb3-persistence.jar" );
+ jars.add( "hibernate-annotations.jar" );
+ jars.add( "hibernate-commons-annotations.jar" );
+ jars.add( "hibernate3.jar" );
+ jars.add( "dom4j-1.6.1.jar" );
+ jars.add( "commons-logging-1.0.4.jar" );
+
+ }
+
+
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ }
+ public static Test suite() {
+ return new TestSuite(CompositeIdJPATest.class);
+ }
+}
+
+
Added:
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/ManyToManyJDK50Test.java
===================================================================
---
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/ManyToManyJDK50Test.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/tools/src/test5.0/org/hibernate/tool/test/jdbc2cfg/ManyToManyJDK50Test.java 2007-11-04
15:40:50 UTC (rev 14188)
@@ -0,0 +1,202 @@
+/*
+ * Created on 2004-12-01
+ *
+ */
+package org.hibernate.tool.test.jdbc2cfg;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.MappingException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.cfg.JDBCMetaDataConfiguration;
+import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
+import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
+import org.hibernate.mapping.Collection;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.tool.JDBCMetaDataBinderTestCase;
+import org.hibernate.tool.hbm2x.HibernateMappingExporter;
+import org.hibernate.tool.hbm2x.POJOExporter;
+
+/**
+ * @author max
+ *
+ */
+public class ManyToManyJDK50Test extends JDBCMetaDataBinderTestCase {
+
+ public static Test suite() {
+ return new TestSuite(ManyToManyJDK50Test.class);
+ }
+
+ private JDBCMetaDataConfiguration localCfg;
+
+ protected void configure(JDBCMetaDataConfiguration configuration) {
+ super.configure( configuration );
+
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ localCfg = new JDBCMetaDataConfiguration();
+
+ DefaultReverseEngineeringStrategy c = new DefaultReverseEngineeringStrategy();
+ c.setSettings(new ReverseEngineeringSettings(c).setDetectManyToMany(false));
+ localCfg.setReverseEngineeringStrategy(c);
+ localCfg.readFromJDBC();
+ }
+ protected void tearDown() throws Exception {
+ localCfg = null;
+
+ super.tearDown();
+ }
+
+ public void testNoManyToManyBiDirectional() {
+
+ PersistentClass project = localCfg.getClassMapping("Project");
+
+ assertNotNull(project.getProperty("worksOns"));
+ //assertNotNull(project.getProperty("employee"));
+ assertEquals(3, project.getPropertyClosureSpan());
+ assertEquals("projectId", project.getIdentifierProperty().getName());
+
+ PersistentClass employee = localCfg.getClassMapping("Employee");
+
+ assertNotNull(employee.getProperty("worksOns"));
+ assertNotNull(employee.getProperty("employees"));
+ assertNotNull(employee.getProperty("employee"));
+ //assertNotNull(employee.getProperty("projects"));
+ assertEquals(6, employee.getPropertyClosureSpan());
+ assertEquals("id", employee.getIdentifierProperty().getName());
+
+ PersistentClass worksOn = localCfg.getClassMapping("WorksOn");
+
+ assertNotNull(worksOn.getProperty("project"));
+ assertNotNull(worksOn.getProperty("employee"));
+ assertEquals(2, worksOn.getPropertyClosureSpan());
+ assertEquals("id", worksOn.getIdentifierProperty().getName());
+ }
+
+ public void testAutoCreation() {
+
+ assertNull("No middle class should be generated.", cfg.getClassMapping(
"WorksOn" ));
+
+ assertNotNull("Should create worksontext since one of the foreign keys is
not part of pk", cfg.getClassMapping( "WorksOnContext" ));
+
+ PersistentClass projectClass = cfg.getClassMapping("Project");
+ assertNotNull( projectClass );
+
+ PersistentClass employeeClass = cfg.getClassMapping("Employee");
+ assertNotNull( employeeClass );
+
+ assertPropertyNotExist( projectClass, "worksOns" );
+ assertPropertyNotExist( employeeClass, "worksOns" );
+
+ Property property = employeeClass.getProperty( "projects" );
+ assertNotNull( property);
+ Property property2 = projectClass.getProperty( "employees" );
+ assertNotNull( property2);
+
+ assertTrue(((Collection)property.getValue()).isInverse());
+ assertFalse(((Collection)property2.getValue()).isInverse());
+
+ }
+
+ public void testBuildMappings() {
+
+ localCfg.buildMappings();
+ }
+
+ public void testGenerateAndReadable() throws Exception {
+
+ cfg.buildMappings();
+
+ HibernateMappingExporter hme = new HibernateMappingExporter(cfg, getOutputDir());
+ hme.start();
+
+ getConfiguration().buildMappings();
+ POJOExporter exporter = new POJOExporter(getConfiguration(), getOutputDir());
+ Properties p = new Properties();
+ p.setProperty("jdk5", "true");
+ p.setProperty("ejb3", "true");
+
+ exporter.setProperties(p);
+ exporter.start();
+
+ File file = new File( "ejb3compilable" );
+ file.mkdir();
+
+ ArrayList list = new ArrayList();
+ List jars = new ArrayList();
+ addAnnotationJars(jars);
+
+ new ExecuteContext(getOutputDir(), file, jars) {
+
+ protected void execute() throws Exception {
+ AnnotationConfiguration configuration = new AnnotationConfiguration();
+ configuration.addAnnotatedClass( getUcl().loadClass( "Project" ) );
+ configuration.addAnnotatedClass( getUcl().loadClass( "Employee" ) );
+ configuration.addAnnotatedClass( getUcl().loadClass( "WorksOnContext" )
);
+
+ SessionFactory sf = configuration.buildSessionFactory();
+ Session s = sf.openSession();
+ Query createQuery = s.createQuery("from java.lang.Object");
+ createQuery.list();
+ s.close();
+ sf.close();
+
+ }
+
+ }.run();
+
+ }
+
+ private void addAnnotationJars(List jars) {
+ jars.add( "ejb3-persistence.jar" );
+ jars.add( "hibernate-annotations.jar" );
+ jars.add( "hibernate-commons-annotations.jar" );
+ jars.add( "hibernate3.jar" );
+ jars.add( "dom4j-1.6.1.jar" );
+ jars.add( "commons-logging-1.0.4.jar" );
+
+ }
+
+ private void assertPropertyNotExist(PersistentClass projectClass, String prop) {
+ try {
+ projectClass.getProperty(prop);
+ fail("property " + prop + " should not exist on " +
projectClass);
+ } catch(MappingException e) {
+ // expected
+ }
+ }
+
+ protected String[] getCreateSQL() {
+ return new String[] {
+ "create table PROJECT ( project_id integer not null, name varchar(50), primary
key (project_id) )",
+ "create table EMPLOYEE ( id integer not null, name varchar(50), manager_id
integer, primary key (id), constraint employee_manager foreign key (manager_id) references
EMPLOYEE)",
+ "create table WORKS_ON ( project_id integer not null, employee_id integer not
null, primary key (project_id, employee_id), constraint workson_employee foreign key
(employee_id) references EMPLOYEE, foreign key (project_id) references PROJECT )",
+ "create table WORKS_ON_CONTEXT ( project_id integer not null, employee_id integer
not null, created_by integer, primary key (project_id, employee_id), constraint
workson_ctx_employee foreign key (employee_id) references EMPLOYEE, foreign key
(project_id) references PROJECT, foreign key (created_by) references EMPLOYEE )",
+ //"alter table PROJECT add constraint project_manager foreign key (team_lead)
references EMPLOYEE"
+ };
+ }
+
+ protected String[] getDropSQL() {
+ return new String[] {
+ //"alter table PROJECT drop constraint project_manager",
+ "drop table WORKS_ON_CONTEXT",
+ "drop table WORKS_ON",
+ "drop table EMPLOYEE",
+ "drop table PROJECT",
+ };
+ }
+
+}