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 2008/12/05 21:27:01 UTC

svn commit: r723851 - in /openjpa/branches/1.2.x: ./ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/ openjpa-persi...

Author: mikedd
Date: Fri Dec  5 12:27:01 2008
New Revision: 723851

URL: http://svn.apache.org/viewvc?rev=723851&view=rev
Log:
OPENJPA-817 preserve order of statements with ConstraintUpdateManager

Added:
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java   (with props)
Modified:
    openjpa/branches/1.2.x/   (props changed)
    openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConstraintUpdateManager.java
    openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowManagerImpl.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java

Propchange: openjpa/branches/1.2.x/
------------------------------------------------------------------------------
    svn:mergeinfo = /openjpa/trunk:708722

Modified: openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConstraintUpdateManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConstraintUpdateManager.java?rev=723851&r1=723850&r2=723851&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConstraintUpdateManager.java (original)
+++ openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConstraintUpdateManager.java Fri Dec  5 12:27:01 2008
@@ -58,7 +58,7 @@
         (ConstraintUpdateManager.class);
 
     public boolean orderDirty() {
-        return false;
+        return true;
     }
 
     protected PreparedStatementManager newPreparedStatementManager

Modified: openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowManagerImpl.java?rev=723851&r1=723850&r2=723851&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowManagerImpl.java (original)
+++ openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowManagerImpl.java Fri Dec  5 12:27:01 2008
@@ -22,7 +22,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -39,17 +39,17 @@
 public class RowManagerImpl
     implements RowManager {
 
-    private Map _inserts = null;
-    private Map _updates = null;
-    private Map _deletes = null;
-    private Collection _secondaryUpdates = null;
-    private Collection _secondaryDeletes = null;
-    private Collection _allRowUpdates = null;
-    private Collection _allRowDeletes = null;
+    private Map<Key, PrimaryRow> _inserts = null;
+    private Map<Key, PrimaryRow> _updates = null;
+    private Map<Key, PrimaryRow> _deletes = null;
+    private Collection<SecondaryRow> _secondaryUpdates = null;
+    private Collection<SecondaryRow> _secondaryDeletes = null;
+    private Collection<Row> _allRowUpdates = null;
+    private Collection<Row> _allRowDeletes = null;
 
     // we maintain a list of the order of all primary rows if the user
     // wants to be able to fetch them in order
-    private final List _primaryOrder;
+    private final List<PrimaryRow> _primaryOrder;
 
     // track whether we're dealing with any auto-inc columns
     private boolean _auto = false;
@@ -66,7 +66,7 @@
      * @param order whether to keep track of the order in which rows are added
      */
     public RowManagerImpl(boolean order) {
-        _primaryOrder = (order) ? new ArrayList() : null;
+        _primaryOrder = (order) ? new ArrayList<PrimaryRow>() : null;
     }
 
     /**
@@ -80,61 +80,98 @@
      * Return the ordered primary rows. Only available if ordering requested
      * on construction.
      */
-    public List getOrdered() {
-        return (_primaryOrder == null) ? Collections.EMPTY_LIST : _primaryOrder;
+    public List<PrimaryRow> getOrdered() {
+        if(_primaryOrder == null ) { 
+            return Collections.emptyList();
+        }
+        else { 
+            return _primaryOrder;
+        }
     }
 
     /**
      * Return all inserted primary rows.
      */
-    public Collection getInserts() {
-        return (_inserts == null) ? Collections.EMPTY_LIST : _inserts.values();
+    public Collection<PrimaryRow> getInserts() {
+        if(_inserts == null ) {
+            return Collections.emptyList();
+        }
+        else {
+            return _inserts.values();
+        }
     }
 
     /**
      * Return all updated primary rows.
      */
-    public Collection getUpdates() {
-        return (_updates == null) ? Collections.EMPTY_LIST : _updates.values();
+    public Collection<PrimaryRow> getUpdates() {
+        if(_updates == null ){ 
+            return Collections.emptyList();
+        }
+        else { 
+            return _updates.values();
+        }
     }
 
     /**
      * Return all deleted primary rows.
      */
-    public Collection getDeletes() {
-        return (_deletes == null) ? Collections.EMPTY_LIST : _deletes.values();
+    public Collection<PrimaryRow> getDeletes() {
+        if(_deletes == null) { 
+            return Collections.emptyList();
+        }
+        else {
+            return _deletes.values();
+        }
     }
 
     /**
      * Return all inserted and updated secondary rows.
      */
-    public Collection getSecondaryUpdates() {
-        return (_secondaryUpdates == null) ? Collections.EMPTY_LIST
-            : _secondaryUpdates;
+    public Collection<SecondaryRow> getSecondaryUpdates() {
+        if(_secondaryUpdates == null) { 
+            return Collections.emptyList();
+        }
+        else { 
+            return _secondaryUpdates;
+        }
     }
 
     /**
      * Return all deleted secondary rows.
      */
-    public Collection getSecondaryDeletes() {
-        return (_secondaryDeletes == null) ? Collections.EMPTY_LIST
-            : _secondaryDeletes;
+    public Collection<SecondaryRow> getSecondaryDeletes() {
+        if(_secondaryDeletes == null) { 
+            return Collections.emptyList();
+        }
+        else { 
+            return _secondaryDeletes;
+        }
     }
 
     /**
      * Return any 'all row' updates.
      */
-    public Collection getAllRowUpdates() {
-        return (_allRowUpdates == null) ? Collections.EMPTY_LIST
-            : _allRowUpdates;
+    public Collection<Row> getAllRowUpdates() {
+        if(_allRowUpdates == null) { 
+            return Collections.emptyList();
+        }
+        else { 
+            return _allRowUpdates;
+        }
     }
 
     /**
      * Return any 'all row' deletes.
      */
-    public Collection getAllRowDeletes() {
-        return (_allRowDeletes == null) ? Collections.EMPTY_LIST
-            : _allRowDeletes;
+    public Collection<Row> getAllRowDeletes() {
+        if(_allRowDeletes == null) { 
+            return Collections.emptyList();
+        }
+        else { 
+            return _allRowDeletes;
+        }
+        
     }
 
     public Row getSecondaryRow(Table table, int action) {
@@ -149,12 +186,12 @@
         SecondaryRow srow = (SecondaryRow) row;
         if (srow.getAction() == Row.ACTION_DELETE) {
             if (_secondaryDeletes == null)
-                _secondaryDeletes = new ArrayList();
-            _secondaryDeletes.add(srow.clone());
+                _secondaryDeletes = new ArrayList<SecondaryRow>();
+            _secondaryDeletes.add((SecondaryRow) srow.clone());
         } else {
             if (_secondaryUpdates == null)
-                _secondaryUpdates = new ArrayList();
-            _secondaryUpdates.add(srow.clone());
+                _secondaryUpdates = new ArrayList<SecondaryRow>();
+            _secondaryUpdates.add((SecondaryRow) srow.clone());
         }
     }
 
@@ -169,12 +206,12 @@
         switch (row.getAction()) {
             case Row.ACTION_UPDATE:
                 if (_allRowUpdates == null)
-                    _allRowUpdates = new ArrayList();
+                    _allRowUpdates = new ArrayList<Row>();
                 _allRowUpdates.add(row);
                 break;
             case Row.ACTION_DELETE:
                 if (_allRowDeletes == null)
-                    _allRowDeletes = new ArrayList();
+                    _allRowDeletes = new ArrayList<Row>();
                 _allRowDeletes.add(row);
                 break;
             default:
@@ -192,25 +229,25 @@
             && _row != null && _row.getAction() == action)
             return _row;
 
-        Map map;
+        Map<Key, PrimaryRow> map;
         if (action == Row.ACTION_DELETE) {
             if (_deletes == null && create)
-                _deletes = new HashMap();
+                _deletes = new LinkedHashMap<Key, PrimaryRow>();
             map = _deletes;
         } else if (action == Row.ACTION_INSERT) {
             if (_inserts == null && create)
-                _inserts = new HashMap();
+                _inserts = new LinkedHashMap<Key, PrimaryRow>();
             map = _inserts;
         } else {
             if (_updates == null && create)
-                _updates = new HashMap();
+                _updates = new LinkedHashMap<Key, PrimaryRow>();
             map = _updates;
         }
         if (map == null)
             return null;
 
         _key = new Key(table, sm);
-        _row = (PrimaryRow) map.get(_key);
+        _row = map.get(_key);
 
         if (_row == null && create) {
             _row = new PrimaryRow(table, action, sm);

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java?rev=723851&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java Fri Dec  5 12:27:01 2008
@@ -0,0 +1,83 @@
+/*
+ * 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.jdbc.kernel;
+
+import java.util.Collection;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Version;
+
+@Entity
+// Try not to collide with other Employee entities
+@Table(name = "PER_JDBC_KERN_EMP")
+public class Employee {
+
+    @Id
+    private int id;
+
+    @Version
+    private int version;
+
+    private String firstName;
+    private String lastName;
+
+    @OneToMany(mappedBy = "employee", cascade = { CascadeType.MERGE,
+        CascadeType.PERSIST })     
+    private Collection<Task> tasks;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public Collection<Task> getTasks() {
+        return tasks;
+    }
+
+    public void setTasks(Collection<Task> tasks) {
+        this.tasks = tasks;
+    }
+
+    public int getVersion() {
+        return version;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Employee.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java?rev=723851&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java Fri Dec  5 12:27:01 2008
@@ -0,0 +1,60 @@
+/*
+ * 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.jdbc.kernel;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Version;
+
+@Entity
+@Table(name = "PER_JDBC_KERN_STORY") // try not to collide
+public class Story {
+    @Id
+    private int id;
+
+    @Version
+    private int version;
+    
+    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
+    private Task task;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public Task getTask() {
+        return task;
+    }
+
+    public void setTask(Task task) {
+        this.task = task;
+    }
+
+    public int getVersion() {
+        return version;
+    } 
+
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Story.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java?rev=723851&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java Fri Dec  5 12:27:01 2008
@@ -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.jdbc.kernel;
+
+import java.util.Collection;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Version;
+
+@Entity
+@Table(name = "PER_JDBC_KERN_TASK")
+// try not to collide
+public class Task {
+    @Id
+    private int id;
+
+    @Version
+    private int version;
+
+    @OneToMany(mappedBy = "task", cascade = { CascadeType.MERGE,
+        CascadeType.PERSIST })
+    private Collection<Story> stories;
+    
+    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
+    private Employee employee;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public Collection<Story> getStories() {
+        return stories;
+    }
+
+    public void setStories(Collection<Story> stories) {
+        this.stories = stories;
+    }
+
+    public Employee getEmployee() {
+        return employee;
+    }
+
+    public void setEmployee(Employee employee) {
+        this.employee = employee;
+    }
+
+    public int getVersion() {
+        return version;
+    } 
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/Task.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java?rev=723851&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java Fri Dec  5 12:27:01 2008
@@ -0,0 +1,115 @@
+/*
+ * 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.jdbc.kernel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
+
+/**
+ * Test that insert order is preserved when using the ConstraintUpdateManager
+ * for entities which are not annotated with ForeignKey constraints.
+ */
+public class TestInsertOrder extends SQLListenerTestCase {
+    private String empTableName;
+    private String taskTableName;
+    private String storyTableName;
+
+    public void setUp() {
+        setUp(Employee.class, Task.class, Story.class);
+        empTableName = getMapping(Employee.class).getTable().getFullName();
+        taskTableName = getMapping(Task.class).getTable().getFullName();
+        storyTableName = getMapping(Story.class).getTable().getFullName();
+    }
+
+    /**
+     * <P>Persist an Employee entity and allow the cascade to insert the children.
+     * The inserts should be executed in this order, Employee, Task, Story.
+     * </P>
+     * 
+     * <P> 
+     * Originally this test would pass in some scenarios. I believe the order 
+     * relied on the hashcode of the underlying entities. 
+     * </P>
+     */
+    public void testCascadePersist() {
+        Employee e = newTree(10);
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        em.persist(e);
+        em.getTransaction().commit();
+        em.close();
+
+        assertSQLOrder("INSERT INTO " + empTableName + ".*", "INSERT INTO "
+            + taskTableName + ".*", "INSERT INTO " + storyTableName + ".*");
+    }
+    
+    /**
+     * Merge an Employee entity and allow the cascade to insert the children.
+     * The inserts should be executed in this order, Employee, Task, Story.
+     */
+    public void testCascadeMerge() {
+        Employee e = newTree(11);
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        em.merge(e);
+        em.getTransaction().commit();
+        em.close();
+
+        assertSQLOrder("INSERT INTO " + empTableName + ".*", "INSERT INTO "
+            + taskTableName + ".*", "INSERT INTO " + storyTableName + ".*");
+    }
+
+
+    /**
+     * Helper to create a tree of entities
+     * 
+     * @param id
+     *            ID for the entities.
+     * @return an unmanaged Employee instance with the appropriate relationships
+     *         set.
+     */
+    private Employee newTree(int id) {
+        Employee e = new Employee();
+        e.setId(id);
+
+        Task t = new Task();
+        t.setId(id);
+
+        Story s = new Story();
+        s.setId(id);
+
+        Collection<Task> tasks = new ArrayList<Task>();
+        tasks.add(t);
+
+        Collection<Story> stories = new ArrayList<Story>();
+        stories.add(s);
+
+        e.setTasks(tasks);
+        t.setEmployee(e);
+
+        t.setStories(stories);
+        s.setTask(t);
+
+        return e;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestInsertOrder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java?rev=723851&r1=723850&r2=723851&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java (original)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java Fri Dec  5 12:27:01 2008
@@ -20,7 +20,6 @@
 
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Map;
 
 import org.apache.openjpa.lib.jdbc.AbstractJDBCListener;
 import org.apache.openjpa.lib.jdbc.JDBCEvent;
@@ -33,7 +32,7 @@
  */
 public abstract class SQLListenerTestCase
     extends SingleEMFTestCase {
-
+    private static String _nl = System.getProperty("line.separator");
     protected List<String> sql = new ArrayList<String>();
     protected int sqlCount;
     
@@ -122,4 +121,28 @@
             }
 		}
 	}
+    
+    public void assertSQLOrder(String... expected) {
+        int hits = 0;
+
+        for (String executedSQL : sql) {
+            if (executedSQL.matches(expected[hits])) {
+                hits++;
+            }
+        }
+
+        if (hits != expected.length) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Did not find SQL in expected order : ").append(_nl);
+            for (String s : expected) {
+                sb.append(s).append(_nl);
+            }
+
+            sb.append("SQL Statements issued : ");
+            for (String s : sql) {
+                sb.append(s).append(_nl);
+            }
+            fail(sb.toString());
+        }
+    }
 }