diff --git a/artemis_sqlmap/Dbxref.xml b/artemis_sqlmap/Dbxref.xml
index b2da012b28745336f7f41c049a5619acc0f3a5a5..435a4d09b81c1d1ec7d187b9bb47bf3a7f3e6c2e 100644
--- a/artemis_sqlmap/Dbxref.xml
+++ b/artemis_sqlmap/Dbxref.xml
@@ -18,7 +18,7 @@
            
   <resultMap id="select-feature-dbxref" 
                class="FeatureDbxref">
-    <result property="feature_id"       column="feature_id"/>
+    <result property="feature.id"       column="feature_id"/>
     <result property="dbxref.db.name"   column="name"/>
     <result property="dbxref.accession" column="accession"/>
     <result property="dbxref.version"   column="version"/>
@@ -66,14 +66,15 @@
      WHERE dbxref_id=
            (SELECT dbxref_id FROM dbxref WHERE accession=#dbxref.accession#
             AND db_id=(SELECT db_id FROM db WHERE name=#dbxref.db.name#))
-     AND feature_id=$feature_id$
+     AND feature_id=
+           (SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#)
   </delete>
   
   <insert id="insertFeatureDbxref" parameterClass="FeatureDbxref">
     INSERT INTO feature_dbxref 
            (feature_id, dbxref_id, is_current)
            VALUES
-           ($feature_id$, $dbxref_id$, $current$)
+           ($feature.id$, $dbxref_id$, $current$)
   </insert>
   
   <insert id="insertDbxref" parameterClass="Dbxref">
diff --git a/artemis_sqlmap/Feature.xml b/artemis_sqlmap/Feature.xml
index 337577809e290d2955dd03231c94f6bc6c867bbe..0b01852f46b242341275c8deaa843dc4dd906771 100644
--- a/artemis_sqlmap/Feature.xml
+++ b/artemis_sqlmap/Feature.xml
@@ -9,9 +9,15 @@
  
      <typeAlias alias="Feature"
         type="uk.ac.sanger.artemis.chado.Feature"/>
+     
+     <typeAlias alias="FeatureLoc"
+        type="uk.ac.sanger.artemis.chado.FeatureLoc"/>
+     
+     <typeAlias alias="FeatureProp"
+        type="uk.ac.sanger.artemis.chado.FeatureProp"/>
         
-     <typeAlias alias="ChadoTransaction"
-        type="uk.ac.sanger.artemis.chado.ChadoTransaction"/>
+     <typeAlias alias="FeatureRelationship"
+        type="uk.ac.sanger.artemis.chado.FeatureRelationship"/>
      
     <parameterMap id="schema-cvlist" 
                   class="Feature">
@@ -23,7 +29,7 @@
                class="Feature">
         <result property="timelastmodified" column="timelastmodified"/>
    	    <result property="id" column="id"/>
-  	    <result property="feature_relationship.object_id" column="object_id"/>
+  	    <result property="feature_relationship.object.id" column="object_id"/>
   	    <result property="feature_relationship.cvterm.cvtermId" column="relation_type_id"/>
   	    <result property="feature_relationship.rank" column="rank"/>
         <result property="featureloc.strand" column="strand" nullValue="0"/>
@@ -58,7 +64,7 @@
                                            select="getFeatureRelationship" />  
         <result property="featureRelationshipsForSubjectId" column="{subject_id=id}" 
                                            select="getFeatureRelationship" /> 
-        <result property="featureSynonymsForFeatureId" column="{uniquename=uniquename}" 
+        <result property="featureSynonymsForFeatureId" column="{feature.uniquename=uniquename}" 
                                            select="getLazyFeatureSynonymsByUniquename" />                          
         <result property="organism" column="organism_id" select="getOrganism" />
      </resultMap>
@@ -74,23 +80,23 @@
      </resultMap>
 
      <resultMap id="select-featureprop" 
-                class="uk.ac.sanger.artemis.chado.FeatureProp">
+                class="FeatureProp">
         <result property="value" column="value" />
         <result property="rank" column="rank" />
         <result property="cvterm" column="type_id" select="selectCvterm" />
      </resultMap>
      
      <resultMap id="select-relationship" 
-                class="uk.ac.sanger.artemis.chado.FeatureRelationship">
-        <result property="subject_id" column="subject_id" />
-        <result property="object_id" column="object_id" />
+                class="FeatureRelationship">
+        <result property="subject.id" column="subject_id" />
+        <result property="object.id" column="object_id" />
         <result property="value" column="value" />
         <result property="rank" column="rank" />
         <result property="cvterm" column="type_id" select="selectCvterm" />
      </resultMap>
      
      <resultMap id="select-location"
-                class="uk.ac.sanger.artemis.chado.FeatureLoc">
+                class="FeatureLoc">
         <result property="srcfeature_id" column="srcfeature_id" nullValue="-999" />
         <result property="fmin"   column="fmin"   nullValue="-999" />
         <result property="fmax"   column="fmax"   nullValue="-999" />
@@ -134,30 +140,7 @@
      </select>
      
 
-     <!-- get feature id -->
-     <select id="getFeatureID" parameterClass="ChadoTransaction"
-                               resultClass="Feature">
-        SELECT feature_id AS id, uniquename FROM feature WHERE
-        <dynamic>
-          <isNotNull property="uniquename">
-            <iterate property="uniquename" conjunction="OR">
-               feature.uniquename='$uniquename[]$'
-            </iterate>
-          </isNotNull>
-          
-          <isNotNull property="parents">
-            <iterate property="parents" conjunction="OR">
-               feature.uniquename='$parents[]$'
-            </iterate>
-          </isNotNull>
-          
-          <isNotNull property="derives_from">
-            <iterate property="derives_from" conjunction="OR">
-               feature.uniquename='$derives_from[]$'
-            </iterate>
-          </isNotNull>
-        </dynamic>
-     </select>
+     <!-- get feature -->
 
      <select id="getFeature" parameterClass="Feature" 
                              resultMap="select-feature">
@@ -193,7 +176,7 @@
      </select>
  
      <select id="getLazyFeature" resultMap ="select-feature-lazy" 
-                            parameterClass="Feature">
+                                 parameterClass="Feature">
 	 SELECT
 	    timelastmodified,
 	 	f.feature_id AS id,
@@ -212,18 +195,18 @@
           
           <isNotNull property="uniquename">                                 
             <isNotNull property="featureSynonymsForFeatureId">
-              <iterate property="featureSynonymsForFeatureId" conjunction="OR" open="(" close=" OR">
+              <iterate property="featureSynonymsForFeatureId" conjunction="OR" open="(" close=") OR">
                f.feature_id=#featureSynonymsForFeatureId[].feature_id#
              </iterate>
             </isNotNull>
-            uniquename LIKE #uniquename# OR name LIKE #uniquename# ) AND              
+            uniquename LIKE #uniquename# OR name LIKE #uniquename# AND              
           </isNotNull>
           
           <isGreaterThan property="cvterm.cvtermId" compareValue="0"> 
             feature.type_id=$cvterm.cvtermId$ AND
           </isGreaterThan>
        </dynamic>
-         f.feature_id > 0
+         f.feature_id > 0 
     </select>
 
     <select id="getSchema" resultClass="java.lang.String">
@@ -270,62 +253,61 @@
     </select>
 
 
-    <!--  WRITE BACK METHODS -->
-    <update id="updateAttributes" 
-            parameterClass="ChadoTransaction">
-      UPDATE $chadoTable$
-      SET
-      <iterate property="properties" conjunction=",">
-         $properties[]$
-      </iterate>
-
-      <isNotEqual property="chadoTable" compareValue="feature">
-        FROM feature
-      </isNotEqual>
-
-      WHERE
-           feature.feature_id=$chadoTable$.feature_id AND (
-      <iterate property="uniquename" conjunction="OR">
-           feature.uniquename='$uniquename[]$'
-      </iterate>
-      )
-      <dynamic>
-        <isNotNull property="constraint">
-           <iterate prepend="AND" property="constraint" conjunction="AND">
-             $constraint[]$
-           </iterate>
-        </isNotNull>
-      </dynamic>
+    <!--  WRITE BACK METHODS  -->
+    
+    <!--  UPDATE  -->
+    <update id="updateFeatureLoc" 
+            parameterClass="FeatureLoc">
+      UPDATE featureloc
+      SET fmin=$fmin$, fmax=$fmax$, rank=$rank$, strand=$strand$, phase=$phase$
+      WHERE 
+      <isNotNull property="feature.uniquename">
+        feature_id=(SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#)
+      </isNotNull>
     </update>
-
-    <insert id="insertAttributes" 
-            parameterClass="ChadoTransaction">
-      INSERT INTO $chadoTable$
-      ( 
-        feature_id 
-        <iterate prepend="," property="propertiesName" conjunction="," >
-          $propertiesName[]$
-        </iterate>
-      ) VALUES
-      (
-        $feature_id$
-        <iterate prepend="," property="propertiesValue" conjunction="," >
-          $propertiesValue[]$
-        </iterate>
-      )
+    
+    <update id="updateFeature"
+            parameterClass="Feature">
+      UPDATE feature
+      SET uniquename=#uniquename#
+      <isNotNull property="cvterm.cvtermId">
+        , type_id=$cvterm.cvtermId$
+      </isNotNull>
+      <isNotNull property="timelastmodified">
+        , timelastmodified=#timelastmodified#
+      </isNotNull>
+      WHERE feature_id=$id$
+    </update>
+    
+    <update id="updateFeatureProp"
+            parameterClass="FeatureProp">
+      UPDATE featureprop
+      SET value=#value#   
+      WHERE rank=$rank$ AND type_id=$cvterm.cvtermId$ AND 
+            feature_id=(SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#)
+    </update>
+    
+    <update id="updateFeatureRelationshipsForSubjectId" 
+           parameterClass="FeatureRelationship">
+      UPDATE feature_relationship
+      SET
+        rank=$rank$, type_id=$cvterm.cvtermId$
+      WHERE subject_id=
+           ( SELECT feature_id FROM feature WHERE uniquename=#subject.uniquename# )
+      AND   object_id=
+           ( SELECT feature_id FROM feature WHERE uniquename=#object.uniquename# )
+   </update>
+    
+    <!--  INSERT  -->
+    <insert id="insertFeatureProp"
+            parameterClass="FeatureProp">
+      INSERT INTO featureprop
+      ( feature_id, type_id, value, rank )
+      VALUES
+      ( (SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#),
+        $cvterm.cvtermId$, #value#, $rank$ )
     </insert>
 
-    <delete id="deleteAttributes" 
-            parameterClass="ChadoTransaction">
-      DELETE FROM $chadoTable$
-      WHERE
-        <iterate property="constraint" conjunction="AND">
-          $constraint[]$
-        </iterate>
-        AND
-        feature_id=$feature_id$
-    </delete>
-
     <insert id="insertFeature" 
             parameterClass="Feature">
       INSERT INTO feature 
@@ -352,32 +334,42 @@
           $featureloc.phase$ )
     </insert>
 
+   <insert id="insertFeatureRelationship" 
+           parameterClass="FeatureRelationship">
+      INSERT INTO feature_relationship
+        ( subject_id, object_id, type_id )
+      VALUES
+        ( (SELECT feature_id FROM feature WHERE uniquename=#subject.uniquename#),
+          (SELECT feature_id FROM feature WHERE uniquename=#object.uniquename#),
+          $cvterm.cvtermId$ )
+   </insert>
+   
+
+   <!--  DELETE  -->
+   
+   <delete id="deleteFeatureProp"
+           parameterClass="FeatureProp">
+      DELETE FROM featureprop
+      WHERE
+        <isNotNull property="feature.uniquename">
+          feature_id=
+            (SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#)
+          AND
+        </isNotNull>
+        <isGreaterThan property="rank" compareValue="-1">
+           rank=$rank$ AND
+        </isGreaterThan>
+        <isNotNull property="value">
+          value=#value# AND
+        </isNotNull>
+        type_id=$cvterm.cvtermId$
+   </delete>
+   
    <delete id="deleteFeature" 
            parameterClass="Feature">
       DELETE FROM feature
       WHERE uniquename=#uniquename#
    </delete>
    
-   <insert id="insertFeatureRelationship" 
-           parameterClass="Feature">
-      INSERT INTO feature_relationship
-        ( subject_id, object_id, type_id )
-      VALUES
-        ( $feature_relationship.subject_id$,
-          $feature_relationship.object_id$,
-          (SELECT cvterm_id FROM cvterm WHERE name=#feature_relationship.cvterm.name#) )
-   </insert>
 
-   <update id="updateFeatureRelationshipsForSubjectId" 
-           parameterClass="ChadoTransaction">
-      UPDATE feature_relationship
-      SET
-      <iterate property="properties" conjunction=",">
-         $properties[]$
-      </iterate>
-      WHERE feature_relationship.subject_id=
-           ( SELECT feature_id FROM feature WHERE uniquename=#chadoFeature.uniquename# )
-      AND   feature_relationship.object_id=
-           ( SELECT feature_id FROM feature WHERE uniquename=#parent_uniquename# )
-   </update>
 </sqlMap> 
diff --git a/artemis_sqlmap/Synonym.xml b/artemis_sqlmap/Synonym.xml
index d993e7eca38cd87c6b97db7e43ecbb28cd5efd50..0d73c274588a359d36109deca7836a3b48f161fd 100644
--- a/artemis_sqlmap/Synonym.xml
+++ b/artemis_sqlmap/Synonym.xml
@@ -15,7 +15,7 @@
         
     <resultMap id="select-alias" 
                class="FeatureSynonym">
-   	    <result property="feature_id" column="feature_id"/>
+   	    <result property="feature.id" column="feature_id"/>
    	    <result property="synonym_id" column="synonym_id"/>
    	    <result property="pub_id" column="pub_id"/>
    	    <result property="current" column="is_current"/>
@@ -28,7 +28,7 @@
      
      <resultMap id="select-alias-part-lazy" 
                class="FeatureSynonym">
-   	    <result property="feature_id" column="feature_id"/>
+   	    <result property="feature.id" column="feature_id"/>
    	    <result property="synonym_id" column="synonym_id"/>
    	    <result property="pub_id" column="pub_id"/>
    	    <result property="current" column="is_current"/>
@@ -38,7 +38,7 @@
      
      <resultMap id="select-alias-lazy" 
                class="FeatureSynonym">
-   	    <result property="feature_id" column="feature_id"/>
+   	    <result property="feature.id" column="feature_id"/>
    	    <result property="pub_id" column="pub_id"/>
    	    <result property="current" column="is_current"/>
    	    <result property="internal" column="is_internal"/>
@@ -72,8 +72,8 @@
       SELECT fs.* 
       FROM feature_synonym fs 
       LEFT JOIN feature f ON f.feature_id=fs.feature_id 
-      <isNotNull property="uniquename">                        
-          WHERE uniquename=#uniquename#
+      <isNotNull property="feature.uniquename">                        
+          WHERE uniquename=#feature.uniquename#
       </isNotNull>
     </select>
     
@@ -108,13 +108,13 @@
       DELETE FROM feature_synonym WHERE
          synonym_id=$synonym_id$ AND 
          feature_id=(SELECT feature_id FROM feature WHERE  
-         uniquename=#uniquename#)
+         uniquename=#feature.uniquename#)
     </delete>
   
     <insert id="insertFeatureAlias" parameterClass="FeatureSynonym">
       INSERT INTO feature_synonym ( synonym_id, feature_id, pub_id )
       VALUES ( $synonym_id$ , 
-              (SELECT feature_id FROM feature WHERE uniquename=#uniquename#), 
+              (SELECT feature_id FROM feature WHERE uniquename=#feature.uniquename#), 
               1)
     </insert>
   
diff --git a/uk/ac/sanger/artemis/chado/ChadoDAO.java b/uk/ac/sanger/artemis/chado/ChadoDAO.java
index baa3fbf797ce78a578515d8b68c69a7b86777dbf..4fbe4b9d576e6c01588a5141cce65c09793c53e0 100644
--- a/uk/ac/sanger/artemis/chado/ChadoDAO.java
+++ b/uk/ac/sanger/artemis/chado/ChadoDAO.java
@@ -28,11 +28,9 @@ import java.sql.*;
 import java.util.List;
 
 /**
- *
  * Data access object
  * @see		uk.ac.sanger.artemis.chado.JdbcDAO
  * @see		uk.ac.sanger.artemis.chado.IBatisDAO
- *
  */
 public interface ChadoDAO
 {
@@ -172,126 +170,32 @@ public interface ChadoDAO
 //
 // WRITE BACK
 //
-  /**
-   * Update attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn		the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public int updateAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException;
-
-  /**
-   * Insert attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
-   * @throws SQLException
-   */
-  public void insertAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException;
-
-  /**
-   * Delete attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
-   * @throws SQLException
-   */
-  public void deleteAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException;
-
-  /**
-   * Insert a feature into the database defined by the <code>ChadoTransaction</code>.
-   * @param tsn         	the <code>ChadoTransaction</code>
-   * @parma srcfeature_id	the parent feature identifier
-   * @throws SQLException
-   */
-  public void insertFeature
-                    (final ChadoTransaction tsn,
-                     final String srcfeature_id)
-                     throws SQLException;
-
-  /**
-   * Delete a feature from the database defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
-   * @return    number of rows deleted
-   * @throws SQLException
-   */
-  public int deleteFeature
-                    (final ChadoTransaction tsn)
-                     throws SQLException;
   
   /**
-   * Insert a dbxref for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
+   * Merge (update) an already persistent object back to the database 
+   * (at the end of the current transaction, or depending upon flush mode). 
+   * This method is defined in all the DAOs. It's recommended to call it 
+   * through an appropriate one eg SequenceDaoI for FeatureI 
+   * @param o The object to merge
    */
-  public int insertFeatureDbxref(final ChadoTransaction tsn)
-                     throws SQLException;
+  public void merge(Object o) throws SQLException;
   
   /**
-   * Delete a dbxref for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
+   * Save the object to the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI 
+   * for FeatureI 
+   * @param o The object to store
    */
-  public int deleteFeatureDbxref(final ChadoTransaction tsn)
-                     throws SQLException;
+  public void persist(Object o) throws SQLException;
   
   /**
-   * Insert a synonym for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
+   * Remove the object from the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI for 
+   * FeatureI 
+   * @param o The object to delete
    */
-  public int insertFeatureAlias(final ChadoTransaction tsn)
-                     throws SQLException;
-
-  /**
-   * Delete a synonym for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public int deleteFeatureAlias(final ChadoTransaction tsn)
-                     throws SQLException;
-
+  public void delete(Object o) throws SQLException;
   
-  /**
-   * Update feature_relationship for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public void updateFeatureRelationshipsForSubjectId(
-      final ChadoTransaction tsn)
-                     throws SQLException;
-  /**
-   * 
-   * Write the time a feature was last modified
-   * @param uniquename	the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @return  number of rows changed
-   * @throws SQLException
-   */
-  public int writeTimeLastModified
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException;
-
-  /**
-   *
-   * Write the time a feature was last accessed
-   * @param uniquename  the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @return  number of rows changed
-   * @throws SQLException
-   */
-  public int writeTimeAccessioned
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException;
 }
diff --git a/uk/ac/sanger/artemis/chado/ChadoDemo.java b/uk/ac/sanger/artemis/chado/ChadoDemo.java
index f2ff149894cf447aa9b101f92e46c7a160c5156d..2dd5fe0a9b60290b49198342d08a3ec28a72276d 100644
--- a/uk/ac/sanger/artemis/chado/ChadoDemo.java
+++ b/uk/ac/sanger/artemis/chado/ChadoDemo.java
@@ -34,11 +34,8 @@ import java.awt.event.MouseEvent;
 import java.awt.Dimension;
 import java.net.ConnectException;
 import java.sql.SQLException;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Vector;
-import java.util.Hashtable;
-import java.util.Enumeration;
 
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
@@ -55,7 +52,6 @@ import javax.swing.JFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
-import javax.swing.JSeparator;
 import javax.swing.Box;
 import javax.swing.event.ListSelectionListener;
 import javax.swing.event.ListSelectionEvent;
diff --git a/uk/ac/sanger/artemis/chado/ChadoTransaction.java b/uk/ac/sanger/artemis/chado/ChadoTransaction.java
index ec4e78fcc038bd3661e5efa548bd2f96bf4b619b..2b1f8564db19d3d6d422e6dfa3a457415737c7e1 100644
--- a/uk/ac/sanger/artemis/chado/ChadoTransaction.java
+++ b/uk/ac/sanger/artemis/chado/ChadoTransaction.java
@@ -29,179 +29,56 @@ import java.util.Vector;
 import java.util.StringTokenizer;
 import java.sql.Timestamp;
 
+import uk.ac.sanger.artemis.io.GFFStreamFeature;
+
 /**
-*
-* Store information about a SQL transaction <i>e.g</i> UPDATE, INSERT, DELETE
-* a feature or a feature attribute. 
-*
-**/
+ * Store information about a SQL transaction <i>e.g</i> UPDATE, INSERT, DELETE
+ * a feature, featureloc, featureprop, feature_dbxref, feature_synonym. 
+ **/
 public class ChadoTransaction
 {
   //
-  // ATTRIBUTE TRANSACTIONS
+  // FEATURE TRANSACTIONS
   /** update statement */
   public static final int UPDATE = 1;
   /** insert statement */
   public static final int INSERT = 2;
   /** delete statement */
   public static final int DELETE = 3;
-
-  // FEATURE TRANSACTIONS
-  /** insert feature statement */
-  public static final int INSERT_FEATURE = 4;
-  /** delete feature statement */
-  public static final int DELETE_FEATURE = 5;
   
-  // DBXREF TRANSACTIONS
-  public static final int UPDATE_DBXREF = 6;
-  public static final int INSERT_DBXREF = 7;
-  public static final int DELETE_DBXREF = 8;
-  
-  // SYNONYM TRANSACTIONS
-  public static final int INSERT_ALIAS = 9;
-  public static final int DELETE_ALIAS = 10;
-  
-  // FEATURE RELATIONSHIPS
-  public static final int UPDATE_FEATURE_RELATIONSHIP = 11;
-  
-  /** properties store <i>e.g.</i> value=<quote>product=hypothetical protein</quote> */
-  private List properties;
-  /** constraint store <i>e.g.</i> type_id=21078 */
-  protected List constraint;
   /** type of statement <i>e.g.</i> UPDATE, INSERT, DELETE, ... */
   protected int type;
   /** feature unique name */
-  protected String uniquename;
-  /** chado table for this transaction */
-  protected String chadoTable;
-  /** postgres schema */
-  private String schema;
-  /** feature id */
-  private int feature_id;
+  protected String old_uniquename;
   /** chado feature */
   private Feature chadoFeature;
-  /** feature dbxref */
-  private FeatureDbxref dbxref;
-  /** feature synonym */
-  private FeatureSynonym alias;
   /** last time feature was modified */
   private Timestamp lastmodified;
   /** the feature object */
   private Object feature_obj;
-  /** parent uniquenames */
-  private List parents;
-  /** derives_from uniquenames */
-  private List derives_from;
-  /** uniquename of the parent feature */
-  private String parent_uniquename;
+  
+  private GFFStreamFeature gff_feature;
+  
   
   /**
-   * Used to construct a <code>ChadoTransaction</code> that can
-   * be used to describe a SQL transaction.
-   *
-   * <i>e.g.</i> to DELETE a feature and where uniquename is a <code>String</code>:
-   * <blockquote><pre>
-   * ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.DELETE_FEATURE,
-   *                                             uniquename, "feature");
-   * </pre></blockquote>
-   *
-   * Or to INSERT a feature property:
-   * <blockquote><pre>
-   * ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT,
-   *                                             feature_id, "featureprop");
-   * tsn.addProperty("value", "'"+ qualifier_string +"'");
-   * tsn.addProperty("type_id", "'"+cvterm_id+"'");
-   * tsn.addProperty("rank", Integer.toString(value_index));
-   * </pre></blockquote>
-   * 
-   * @param type	the transaction type
-   * @param uniquename	the unique name of feature
-   * @param chadoTable	the chado table used in transaction <i>e.g.</i> 
-   *                 	feature, featureloc....
-   */
-  public ChadoTransaction(int type, String uniquename, 
-                          String chadoTable,
-                          final Timestamp lastmodified,
-                          final Object feature_obj)
-  {
-    this.type = type;
-    this.uniquename = uniquename;
-    this.chadoTable = chadoTable;
-    this.lastmodified = lastmodified;
-    this.feature_obj  = feature_obj;
-  }
- 
-  /**
-   * Used to construct a <code>ChadoTransaction</code> that can
-   * be used to describe a SQL transaction.
-   *
-   * <i>e.g.</i> to INSERT a feature and where chado_feature is a 
-   *        <code>Feature</code>:
-   * <blockquote><pre>
-   * ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT_FEATURE,
-   *                                             chado_feature);
-   * </pre></blockquote>
-   *
-   * @param type          the transaction type
-   * @param chado_feature the <code>Feature</code> to be inserted
-   * @param parents       <code>Vector</code> of parent uniquenames
-   * @param derives_from  <code>Vector</code> of derives_from names
+   * Create a transaction to represent a single insert, delete or
+   * update.
+   * @param type          the type of transcation, e.g. insert, delete, update.
+   * @param feature_obj   the <code>Feature</code>, <code>FeatureLoc</code>,
+   * <code>FeatureProp</code>, <code>FeatureRelationship</code>, <code>FeatureDbxref</code>,
+   * or <code>FeatureSynonym</code>.
+   * @param lastmodified  the last modified timestamp  
+   * @param gff_feature   the artemis GFF feature effected
    */
   public ChadoTransaction(final int type, 
-                          final Feature chadoFeature, 
-                          final Vector parents,
-                          final Vector derives_from)
-  {
-    this.chadoFeature = chadoFeature;
-    this.type         = type;
-    this.parents      = parents;
-    this.derives_from = derives_from;
-  }
-
-  /**
-   * Used to construct a <code>ChadoTransaction</code> that can
-   * be used to describe a SQL transaction.
-   * @param type    the transaction type
-   * @param dbxref  a feature dbxref
-   */
-  public ChadoTransaction(final int type,
-                          final String uniquename,
-                          final FeatureDbxref dbxref, 
+                          final Object feature_obj,
                           final Timestamp lastmodified,
-                          final Object feature_obj)
+                          final GFFStreamFeature gff_feature)
   {
-    this.type   = type;
-    this.dbxref = dbxref;
-    this.uniquename   = uniquename;
+    this.type = type;
     this.lastmodified = lastmodified;
     this.feature_obj  = feature_obj;
-  }
-
-  public ChadoTransaction(final int type,
-                          final FeatureSynonym alias,
-                          final Object feature_obj)
-  {
-    this.type   = type;
-    this.alias  = alias;
-    this.feature_obj = feature_obj;
-  }
-  
-  public ChadoTransaction(final int type,
-                          final Feature chadoFeature,
-                          final String parent_uniquename)
-  {
-    this.type         = type;
-    this.chadoFeature = chadoFeature;
-    this.parent_uniquename = parent_uniquename;
-  }
-  
-  /**
-   * The <code>Dbxref</code> used in a transaction.
-   * @return  the feature dbxref
-   */
-  public FeatureDbxref getFeatureDbxref()
-  {
-    return dbxref;
+    this.gff_feature  = gff_feature;
   }
   
   /**
@@ -213,23 +90,6 @@ public class ChadoTransaction
     return chadoFeature;
   }
 
-  /**
-   * Set the postgres schema.
-   * @param     the postgres schema
-   */
-  public void setSchema(final String schema)
-  {
-    this.schema = schema;
-  }
-
-  /**
-   * Get the postgres schema.
-   * @return    the postgres schema
-   */
-  public String getSchema()
-  {
-    return schema;
-  }
 
   /**
    * The type of SQL transaction
@@ -240,156 +100,31 @@ public class ChadoTransaction
     return type;
   } 
 
-  /**
-   * Get the unique name for a feature.
-   * @return    the unique name for a feature.
-   */
-  public String getUniqueName()
-  {
-    return uniquename;
-  }
-
 
   /**
-   * Get the chado table that is involved in the SQL command
-   * @return 	the chado table
+   * Set the old uniquename, used when updating the uniquename
+   * @param uniquename
    */
-  public String getChadoTable()
+  public void setOldUniquename(final String old_uniquename)
   {
-    return chadoTable;
-  }
-
-
-  /**
-   * Add a property to this transaction that will be updated
-   * or inserted.
-   * @param name	the property name
-   * @param value	the property value
-   */
-  public void addProperty(String name, String value) 
-  {
-    if(properties == null)
-      properties = new Vector();
-
-    properties.add(name+"="+value);
-  }
-
-
-  /**
-   * Set a constraint on this transaction.
-   * @param name	the constraint name
-   * @param value	the constraint value
-   */
-  public void setConstraint(String name, String value)
-  {
-    if(constraint == null)
-      constraint = new Vector();
-    constraint.add(name+"="+value);
-  }
-
-
-  /**
-   * Get the properties for this transaction that will be changed.
-   * @return	the transaction properties used to INSERT/UPDATE 
-   */
-  public List getProperties()
-  {
-    return properties;
-  }
- 
-  /**
-   * Set the properties for this transaction that will be changed.
-   * @param properties	the transaction properties used to INSERT/UPDATE
-   */
-  public void setProperties(List properties)
-  {
-    this.properties = properties;
-  }
-
-  /**
-   * Get the names of the properties for this transaction that will 
-   * be changed.
-   * @return	the names of the properties to INSERT/UPDATE
-   */
-  public List getPropertiesName()
-  {
-    List propertiesName = new Vector();
-    String property;
-    int index;
-    for(int i=0; i<properties.size();i++)
-    {
-      property = (String)properties.get(i);
-      index = property.indexOf("=");
-      propertiesName.add(property.substring(0,index));
-    }
-
-    return propertiesName;
-  }
-
-  /**
-   * Get the values of the properties for this transaction that will  
-   * be changed..
-   * @return	the values of the properties to INSERT/UPDATE
-   */
-  public List getPropertiesValue()
-  {
-    List propertiesValue = new Vector();
-    String property;
-    int index;
-    for(int i=0; i<properties.size();i++)
-    {
-      property = (String)properties.get(i);
-      index = property.indexOf("=");
-      propertiesValue.add(property.substring(index+1));
-    }
-
-    return propertiesValue;
-  }
-
-  /**
-   * Get the constraints on this transaction.
-   * @return 	the transaction constraints	
-   */
-  public List getConstraint()
-  {
-    return constraint;
+    this.old_uniquename = old_uniquename;
   }
 
   /**
    * Get the unique names of features to change.
    */
-  public List getUniquename()
+  public String getOldUniquename()
   {
-    Vector names = new Vector();
-    
-    if(uniquename == null)
-      return names;
-    
-    StringTokenizer tok = new StringTokenizer(uniquename,",");
-    while(tok.hasMoreTokens())
-    {
-      names.add(tok.nextToken());
-    }
-
-    return names;
-  }
-
-  /**
-   * Set the feature id
-   * @param feature_id	the feature identifier
-   */
-  public void setFeature_id(final int feature_id)
-  {
-    this.feature_id = feature_id;
+    return old_uniquename;
   }
-
-  /**
-   * Get the feature id
-   * @return	the feature identifier
-   */
-  public int getFeature_id()
+  
+  public String getUniquename()
   {
-    return feature_id;
+    if(getGff_feature() == null)
+      return null;
+    
+    return (String)
+      getGff_feature().getQualifierByName("ID").getValues().get(0);
   }
 
   /**
@@ -406,44 +141,14 @@ public class ChadoTransaction
     return feature_obj;
   }
 
-  public FeatureSynonym getAlias()
-  {
-    return alias;
-  }
-
-  public void setAlias(FeatureSynonym alias)
-  {
-    this.alias = alias;
-  }
-
-  public List getDerives_from()
-  {
-    return derives_from;
-  }
-
-  public void setDerives_from(Vector derives_from)
-  {
-    this.derives_from = derives_from;
-  }
-
-  public List getParents()
-  {
-    return parents;
-  }
-
-  public void setParents(Vector parents)
-  {
-    this.parents = parents;
-  }
-
-  public String getParent_uniquename()
+  public GFFStreamFeature getGff_feature()
   {
-    return parent_uniquename;
+    return gff_feature;
   }
 
-  public void setParent_uniquename(String parent_uniquename)
+  public void setGff_feature(GFFStreamFeature gff_feature)
   {
-    this.parent_uniquename = parent_uniquename;
+    this.gff_feature = gff_feature;
   }
 
 }
diff --git a/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java b/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
index c834a9b0554d15245036a4116f60232798b459c7..b44abe55e7b7f0d488f5a49dd40ca283f997c725 100644
--- a/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
+++ b/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
@@ -219,7 +219,7 @@ public class ChadoTransactionManager
               
               String segment_uniquename = feature.getSegmentID(range);
               insertFeatureSegment(segment,segment_uniquename);
-//            update feature_relationship.rank
+              // update feature_relationship.rank
               updateFeatureRelationshipRank(feature, rv_new);
             }
           }
@@ -252,15 +252,6 @@ public class ChadoTransactionManager
         {
           ichanged = ((Integer)changes.elementAt(i)).intValue();
           
-          /*
-          Qualifier parent_qualifier = feature.getQualifierByName("Parent");
-          
-          String transcript = null;
-          if(parent_qualifier != null)
-            transcript = 
-               (String)parent_qualifier.getValues().get(0);
-          */
-          
           Range range_new = (Range)rv_new.elementAt(ichanged);
           Range range_old = (Range)rv_old.elementAt(ichanged);
           String seg_id   = feature.getSegmentID(range_new);
@@ -271,15 +262,11 @@ public class ChadoTransactionManager
           if(feature.getSegmentRangeStore() != null)
             feature.getSegmentRangeStore().put(seg_id, range_new);
           
-          tsn = new ChadoTransaction(ChadoTransaction.UPDATE, 
-                                     seg_id, "featureloc", 
-                                     feature.getLastModified(),
-                                     feature);
-
-          if(range_new.getStart() != range_old.getStart())
-            tsn.addProperty("fmin", Integer.toString(range_new.getStart()-1));
-          if(range_new.getEnd() != range_old.getEnd())
-            tsn.addProperty("fmax", Integer.toString(range_new.getEnd()));
+          FeatureLoc featureloc = getFeatureLoc(feature, seg_id, range_new);
+          
+          tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
+                                     featureloc,
+                                     feature.getLastModified(), feature);
 
           sql.add(tsn);
         }
@@ -381,28 +368,53 @@ public class ChadoTransactionManager
   private void updateFeatureRelationshipRank(final GFFStreamFeature feature,
                                              final RangeVector rv_new)
   {
+       
+    
     // update feature_relationship.rank
     ChadoTransaction tsn;
     Hashtable feature_relationship_rank_store = new Hashtable();
-    String parent =
-      (String)feature.getQualifierByName("Parent").getValues().get(0);
+    Qualifier qualifier_relation = feature.getQualifierByName("Parent");
     
-    for(int i=0; i<rv_new.size(); i++)
+    for(int rank=0; rank<rv_new.size(); rank++)
     {
-      Range range   = (Range)rv_new.elementAt(i);
+      Range range   = (Range)rv_new.elementAt(rank);
       String seq_id = feature.getSegmentID(range);
       
       uk.ac.sanger.artemis.chado.Feature chado_feature = 
                new uk.ac.sanger.artemis.chado.Feature();
       chado_feature.setUniquename(seq_id);
-      
-      tsn = new ChadoTransaction(
-              ChadoTransaction.UPDATE_FEATURE_RELATIONSHIP,
-              chado_feature,
-              parent);
-      tsn.addProperty("rank", "'"+ i +"'");
-      sql.add(tsn);
-      feature_relationship_rank_store.put(seq_id, new Integer(i));
+
+      List featureRelationshipsForSubjectId = null;
+      if(qualifier_relation != null)
+      {
+        StringVector parents = qualifier_relation.getValues();
+        if(parents.size() > 0)
+          featureRelationshipsForSubjectId = new Vector();
+        
+        for(int i=0; i<parents.size(); i++)
+        {
+          uk.ac.sanger.artemis.chado.Feature parent =
+              new uk.ac.sanger.artemis.chado.Feature();
+          parent.setUniquename((String)parents.get(i));
+          FeatureRelationship feature_relationship =
+              new FeatureRelationship();
+          Cvterm cvterm = new Cvterm();
+          cvterm.setCvtermId(DatabaseDocument.getCvtermID("part_of").longValue());
+          
+          feature_relationship.setObject(parent);
+          feature_relationship.setSubject(chado_feature);
+          feature_relationship.setCvterm(cvterm);
+          feature_relationship.setRank(rank);
+          featureRelationshipsForSubjectId.add(feature_relationship);
+          
+          tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
+              feature_relationship,
+              feature.getLastModified(), feature);
+          sql.add(tsn);
+        }
+      }
+
+      feature_relationship_rank_store.put(seq_id, new Integer(rank));
     }
     feature.setFeature_relationship_rank_store(feature_relationship_rank_store);  
   }
@@ -454,9 +466,6 @@ public class ChadoTransactionManager
       featureloc.setStrand(1);
     else
       featureloc.setStrand(-1);
-
-    Vector parent_features  = null;
-    Vector derives_features = null;
     
     // codon_start attribute
     try
@@ -476,29 +485,58 @@ public class ChadoTransactionManager
       
       // relationship attributes
       Qualifier qualifier_relation = feature.getQualifierByName("Parent");
+      List featureRelationshipsForSubjectId = null;
       if(qualifier_relation != null)
       {
         StringVector parents = qualifier_relation.getValues();
         if(parents.size() > 0)
-          parent_features = new Vector();
+          featureRelationshipsForSubjectId = new Vector();
         
         for(int i=0; i<parents.size(); i++)
-          parent_features.add((String)parents.get(i));
+        {
+          uk.ac.sanger.artemis.chado.Feature parent =
+              new uk.ac.sanger.artemis.chado.Feature();
+          parent.setUniquename((String)parents.get(i));
+          FeatureRelationship feature_relationship =
+              new FeatureRelationship();
+          Cvterm cvterm = new Cvterm();
+          cvterm.setCvtermId(DatabaseDocument.getCvtermID("part_of").longValue());
+          
+          feature_relationship.setObject(parent);
+          feature_relationship.setSubject(chado_feature);
+          feature_relationship.setCvterm(cvterm);
+          featureRelationshipsForSubjectId.add(feature_relationship);
+        }
       }
       
       qualifier_relation = feature.getQualifierByName("Derives_from");
       if(qualifier_relation != null)
       {
         StringVector derives = qualifier_relation.getValues();
-        if(derives.size() > 0)
-          derives_features = new Vector();
+        if(derives.size() > 0 && featureRelationshipsForSubjectId == null)
+          featureRelationshipsForSubjectId = new Vector();
         
         for(int i=0; i<derives.size(); i++)
-          derives_features.add((String)derives.get(i));
+        {
+          uk.ac.sanger.artemis.chado.Feature parent =
+                                      new uk.ac.sanger.artemis.chado.Feature();
+          parent.setUniquename((String) derives.get(i));
+          FeatureRelationship feature_relationship = new FeatureRelationship();
+          Cvterm cvterm = new Cvterm();
+          cvterm.setCvtermId(DatabaseDocument.getCvtermID("derives_from")
+              .longValue());
+
+          feature_relationship.setObject(parent);
+          feature_relationship.setSubject(chado_feature);
+          feature_relationship.setCvterm(cvterm);
+          featureRelationshipsForSubjectId.add(feature_relationship);
+        }
       }
+      chado_feature.setFeatureRelationshipsForSubjectId(
+                       featureRelationshipsForSubjectId);
     }
     catch(InvalidRelationException ire){}
-
+    
     if(feature.isForwardFeature())
       featureloc.setStrand(1);
     else
@@ -517,10 +555,10 @@ public class ChadoTransactionManager
 
     addQualifiers(feature.getQualifiers(), chado_feature);
     // create transaction object
-    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT_FEATURE,
-                                                chado_feature,
-                                                parent_features, 
-                                                derives_features);
+    
+    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+                               chado_feature,
+                               null, (GFFStreamFeature)null);
     sql.add(tsn);  
   }
   
@@ -540,9 +578,6 @@ public class ChadoTransactionManager
       featureloc.setStrand(1);
     else
       featureloc.setStrand(-1);
-
-    Vector parent_features  = null;
-    Vector derives_features = null;
     
     // codon_start attribute
     Feature feature = segment.getFeature();
@@ -563,26 +598,55 @@ public class ChadoTransactionManager
       
       // relationship attributes
       Qualifier qualifier_relation = feature.getQualifierByName("Parent");
+      List featureRelationshipsForSubjectId = null;
       if(qualifier_relation != null)
       {
         StringVector parents = qualifier_relation.getValues();
         if(parents.size() > 0)
-          parent_features = new Vector();
+          featureRelationshipsForSubjectId = new Vector();
         
         for(int i=0; i<parents.size(); i++)
-          parent_features.add((String)parents.get(i));
+        {
+          uk.ac.sanger.artemis.chado.Feature parent =
+              new uk.ac.sanger.artemis.chado.Feature();
+          parent.setUniquename((String)parents.get(i));
+          FeatureRelationship feature_relationship =
+              new FeatureRelationship();
+          Cvterm cvterm = new Cvterm();
+          cvterm.setCvtermId(DatabaseDocument.getCvtermID("part_of").longValue());
+          
+          feature_relationship.setObject(parent);
+          feature_relationship.setSubject(chado_feature);
+          feature_relationship.setCvterm(cvterm);
+          featureRelationshipsForSubjectId.add(feature_relationship);
+        }
       }
       
       qualifier_relation = feature.getQualifierByName("Derives_from");
       if(qualifier_relation != null)
       {
         StringVector derives = qualifier_relation.getValues();
-        if(derives.size() > 0)
-          derives_features = new Vector();
+        if(derives.size() > 0 && featureRelationshipsForSubjectId == null)
+          featureRelationshipsForSubjectId = new Vector();
         
         for(int i=0; i<derives.size(); i++)
-          derives_features.add((String)derives.get(i));
+        {
+          uk.ac.sanger.artemis.chado.Feature parent =
+                                      new uk.ac.sanger.artemis.chado.Feature();
+          parent.setUniquename((String) derives.get(i));
+          FeatureRelationship feature_relationship = new FeatureRelationship();
+          Cvterm cvterm = new Cvterm();
+          cvterm.setCvtermId(DatabaseDocument.getCvtermID("derives_from")
+              .longValue());
+
+          feature_relationship.setObject(parent);
+          feature_relationship.setSubject(chado_feature);
+          feature_relationship.setCvterm(cvterm);
+          featureRelationshipsForSubjectId.add(feature_relationship);
+        }
       }
+      chado_feature.setFeatureRelationshipsForSubjectId(
+                       featureRelationshipsForSubjectId);
     }
     catch(InvalidRelationException ire){}
 
@@ -599,22 +663,27 @@ public class ChadoTransactionManager
 
     //addQualifiers(feature.getQualifiers(), chado_feature);
     // create transaction object
-    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT_FEATURE,
-                                                chado_feature,
-                                                parent_features, 
-                                                derives_features);
+    
+    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+        chado_feature,
+        null, (GFFStreamFeature)null);
+   
     sql.add(tsn);  
   }
   
   /**
    * Set the transaction for deleting a feature.
-   * @param feature
    */
-  private void deleteFeature(final String feature_uniquename)
+  private void deleteFeature(final String uniquename)
   {
-    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.DELETE_FEATURE,
-                                                feature_uniquename, "feature",
-                                                null, null);
+    uk.ac.sanger.artemis.chado.Feature chado_feature = 
+      new uk.ac.sanger.artemis.chado.Feature();
+    chado_feature.setUniquename(uniquename);
+    
+    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+        chado_feature,
+        null, (GFFStreamFeature)null);
+
     sql.add(tsn); 
   }
 
@@ -710,7 +779,7 @@ public class ChadoTransactionManager
                                     final Key new_key,
                                     final GFFStreamFeature feature)
   {
-    final String uniquename = (String)(feature.getQualifierByName("ID").getValues()).elementAt(0);
+    String uniquename = (String)(feature.getQualifierByName("ID").getValues()).elementAt(0);
     ChadoTransaction tsn;
 
     // updating the key
@@ -726,12 +795,19 @@ public class ChadoTransactionManager
                   JOptionPane.WARNING_MESSAGE);
       }
       else
-      {
+      {  
+        uk.ac.sanger.artemis.chado.Feature chado_feature =
+           new uk.ac.sanger.artemis.chado.Feature();
+        Cvterm cvterm = new Cvterm();
+        cvterm.setCvtermId( lcvterm_id.longValue() );
+        
+        chado_feature.setCvterm(cvterm);
+        chado_feature.setUniquename(uniquename);
+        
         tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
-                                   uniquename, "feature",
-                                   feature.getLastModified(),
-                                   feature);
-        tsn.addProperty("type_id", "'"+ lcvterm_id.toString() +"'");
+            chado_feature,
+            feature.getLastModified(), feature);
+
         sql.add(tsn);
       }
     }
@@ -764,13 +840,32 @@ public class ChadoTransactionManager
           continue;
         }
 
-        String cvterm_id = lcvterm_id.toString();
-        tsn = new ChadoTransaction(ChadoTransaction.DELETE,
-                                   uniquename, "featureprop",
-                                   feature.getLastModified(),
-                                   feature);
-        tsn.setConstraint("type_id", cvterm_id);
-        sql.add(tsn);
+        
+        if(feature.getFeature_relationship_rank_store() != null)
+        {
+          Hashtable rank_hash = feature.getFeature_relationship_rank_store();
+          Enumeration id_keys= rank_hash.keys();
+          while(id_keys.hasMoreElements())
+          {
+            uniquename = (String)id_keys.nextElement();
+            FeatureProp featureprop = getFeatureProp(uniquename, null,
+                lcvterm_id, -1);
+            tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+                featureprop,
+                feature.getLastModified(), feature);
+            sql.add(tsn);
+          }
+        }
+        else
+        {
+          FeatureProp featureprop = getFeatureProp(uniquename,
+                                        null, lcvterm_id, -1);
+        
+          tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+              featureprop,
+              feature.getLastModified(), feature);       
+          sql.add(tsn);
+        }
       }
     }
 
@@ -817,10 +912,10 @@ public class ChadoTransactionManager
       }
       
       // get the cvterm_id for this featureprop/qualifier
-      String cvterm_id = null;
+      Long lcvterm_id = null;
       if(!name.equals("timelastmodified"))
       {
-        Long lcvterm_id = DatabaseDocument.getCvtermID(name);
+        lcvterm_id = DatabaseDocument.getCvtermID(name);
 
         if(lcvterm_id == null)   // chado doesn't recognise this
         {
@@ -831,7 +926,6 @@ public class ChadoTransactionManager
                     JOptionPane.WARNING_MESSAGE);
           continue;
         }
-        cvterm_id = lcvterm_id.toString();
       }
 
       if(old_index > -1 &&
@@ -842,22 +936,40 @@ public class ChadoTransactionManager
         //
         for(int rank = 0; rank < new_qualifier_strings.size();
             ++rank)
-        {
+        {         
           String qualifier_string = (String)new_qualifier_strings.elementAt(rank);
           int index = qualifier_string.indexOf("=");
 
           if(index > -1)
             qualifier_string = qualifier_string.substring(index+1);
           
-          tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
-                                     uniquename, "featureprop",
-                                     feature.getLastModified(),
-                                     feature);
+          if(feature.getFeature_relationship_rank_store() != null)
+          {
+            Hashtable rank_hash = feature.getFeature_relationship_rank_store();
+            Enumeration id_keys= rank_hash.keys();
+            while(id_keys.hasMoreElements())
+            {
+              uniquename = (String)id_keys.nextElement();
+              FeatureProp featureprop = getFeatureProp(uniquename, 
+                  qualifier_string,
+                  lcvterm_id, rank);
+              tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
+                  featureprop,
+                  feature.getLastModified(), feature);
+              tsn.setGff_feature(feature);
+              sql.add(tsn);
+            }
+          }
+          else
+          {
+            FeatureProp featureprop = getFeatureProp(uniquename,
+                qualifier_string, lcvterm_id, rank);
 
-          tsn.addProperty("value", "'"+ stripQuotes(qualifier_string) +"'");
-          tsn.setConstraint("featureprop.type_id", "'"+cvterm_id+"'");
-          tsn.setConstraint("rank", Integer.toString(rank));
-          sql.add(tsn);
+            tsn = new ChadoTransaction(ChadoTransaction.UPDATE, featureprop,
+                feature.getLastModified(), feature);
+            tsn.setGff_feature(feature);
+            sql.add(tsn);
+          }
         }
 
       }
@@ -868,13 +980,34 @@ public class ChadoTransactionManager
         //
         if(old_index > -1)
         {
-          tsn = new ChadoTransaction(ChadoTransaction.DELETE,
-                                     uniquename, "featureprop",
-                                     feature.getLastModified(),
-                                     feature);
+          if(feature.getFeature_relationship_rank_store() != null)
+          {
+            Hashtable rank_hash = feature.getFeature_relationship_rank_store();
+            Enumeration id_keys= rank_hash.keys();
+            while(id_keys.hasMoreElements())
+            {
+              uniquename = (String)id_keys.nextElement();
+              FeatureProp featureprop = getFeatureProp(uniquename, null,
+                  lcvterm_id, -1);
+              tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+                  featureprop,
+                  feature.getLastModified(), feature);
+              tsn.setGff_feature(feature);
+              sql.add(tsn);
+            }
+          }
+          else
+          {
+            FeatureProp featureprop = getFeatureProp(uniquename, null,
+                lcvterm_id, -1);
+          
+            tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+                featureprop,
+                feature.getLastModified(), feature);
 
-          tsn.setConstraint("type_id", cvterm_id);
-          sql.add(tsn);
+            tsn.setGff_feature(feature);
+            sql.add(tsn);
+          }
         }
           
         //
@@ -888,17 +1021,30 @@ public class ChadoTransactionManager
           if(index > -1)
             qualifier_string = qualifier_string.substring(index+1);
          
-          tsn = new ChadoTransaction(ChadoTransaction.INSERT,
-                                     uniquename, "featureprop",
-                                     feature.getLastModified(),
-                                     feature);
-
-          tsn.addProperty("value", "'"+ stripQuotes(qualifier_string) +"'");
-          tsn.addProperty("type_id", "'"+cvterm_id+"'");
-          tsn.addProperty("rank", Integer.toString(rank));
-
-          if(tsn !=null)
+          if(feature.getFeature_relationship_rank_store() != null)
+          {
+            Hashtable rank_hash = feature.getFeature_relationship_rank_store();
+            Enumeration id_keys= rank_hash.keys();
+            while(id_keys.hasMoreElements())
+            {
+              uniquename = (String)id_keys.nextElement();
+              FeatureProp featureprop = getFeatureProp(uniquename, qualifier_string,
+                  lcvterm_id, rank);
+              tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+                  featureprop,
+                  feature.getLastModified(), feature);
+              sql.add(tsn);
+            }
+          }
+          else
+          {
+            FeatureProp featureprop = getFeatureProp(uniquename, qualifier_string,
+                                                   lcvterm_id, rank);
+            tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+                featureprop,
+                feature.getLastModified(), feature);
             sql.add(tsn);
+          }
         }
 
       }
@@ -944,14 +1090,16 @@ public class ChadoTransactionManager
       if(new_qualifier.getValues() == null)
         return;
       
-      uniquename = (String) old_qualifier.getValues().get(0);
+      uk.ac.sanger.artemis.chado.Feature chado_feature =
+        new uk.ac.sanger.artemis.chado.Feature();
+     
+      chado_feature.setUniquename((String)new_qualifier.getValues().get(0));
+     
       ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
-          uniquename, "feature",
-          feature.getLastModified(),
-          feature);
-
-      tsn.addProperty("uniquename", "'" + 
-          stripQuotes((String) new_qualifier.getValues().get(0)) + "'");
+                chado_feature,
+                feature.getLastModified(), feature);
+      tsn.setOldUniquename( (String)old_qualifier.getValues().get(0) );
+     
       sql.add(tsn);
       return;
     }
@@ -976,17 +1124,20 @@ public class ChadoTransactionManager
                qualifier_string.substring(0,index)+" acc="+qualifier_string.substring(index+1));
          
            FeatureDbxref old_dbxref = new FeatureDbxref();
+           uk.ac.sanger.artemis.chado.Feature chado_feature = 
+             new uk.ac.sanger.artemis.chado.Feature();
            Dbxref dbxref = new Dbxref();
            Db db = new Db();
            db.setName(qualifier_string.substring(0,index));
            dbxref.setAccession(qualifier_string.substring(index+1));
            dbxref.setDb(db);
+           chado_feature.setUniquename(uniquename);
            old_dbxref.setDbxref(dbxref);
-
-           tsn = new ChadoTransaction(ChadoTransaction.DELETE_DBXREF, 
-                                      uniquename, old_dbxref,
-                                      feature.getLastModified(),
-                                      feature);
+           old_dbxref.setFeature(chado_feature);
+           
+           tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+               old_dbxref,
+               feature.getLastModified(), feature);  
          }
          else if(isSynonymTag(qualifier_name))
          {
@@ -994,15 +1145,18 @@ public class ChadoTransactionManager
                               qualifier_string);
            
            FeatureSynonym alias = new FeatureSynonym();
+           uk.ac.sanger.artemis.chado.Feature chado_feature =
+             new uk.ac.sanger.artemis.chado.Feature();
+           chado_feature.setUniquename(uniquename);
+           
            Synonym synonym = new Synonym();
            synonym.setName(qualifier_string);
            alias.setSynonym(synonym);
-           alias.setUniquename(uniquename);
+           alias.setFeature(chado_feature);
           
-           tsn = new ChadoTransaction(ChadoTransaction.DELETE_ALIAS, 
-                                      alias, 
-                                      feature);
-           //tsn.setConstraint("synonym.name", "'"+qualifier_string+"'");      
+           tsn = new ChadoTransaction(ChadoTransaction.DELETE,
+               alias,
+               feature.getLastModified(), feature);   
          }
          sql.add(tsn);
       }
@@ -1033,11 +1187,14 @@ public class ChadoTransactionManager
            dbxref.setDb(db);
            dbxref.setAccession(qualifier_string.substring(index+1));
            new_dbxref.setDbxref(dbxref);
-
-           tsn = new ChadoTransaction(ChadoTransaction.INSERT_DBXREF, 
-                                      uniquename, new_dbxref, 
-                                      feature.getLastModified(),
-                                      feature);
+           uk.ac.sanger.artemis.chado.Feature feat = 
+             new uk.ac.sanger.artemis.chado.Feature();
+           feat.setUniquename(uniquename);
+           new_dbxref.setFeature(feat);
+           
+           tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+               new_dbxref,
+               feature.getLastModified(), feature);
          }
          else if(isSynonymTag(qualifier_name))
          {
@@ -1045,6 +1202,10 @@ public class ChadoTransactionManager
                qualifier_string);
            Long lcvterm_id = DatabaseDocument.getCvtermID(qualifier_name);
            FeatureSynonym alias = new FeatureSynonym();
+           uk.ac.sanger.artemis.chado.Feature chado_feature = 
+             new uk.ac.sanger.artemis.chado.Feature();
+           chado_feature.setUniquename(uniquename);
+           
            Synonym synonym = new Synonym();
            Cvterm cvterm = new Cvterm();
            cvterm.setCvtermId(lcvterm_id.longValue());
@@ -1052,14 +1213,11 @@ public class ChadoTransactionManager
            synonym.setCvterm(cvterm);
            
            alias.setSynonym(synonym);
-           alias.setUniquename(uniquename);
+           alias.setFeature(chado_feature);
 
-           
-           tsn = new ChadoTransaction(ChadoTransaction.INSERT_ALIAS, 
-                                      alias, 
-                                      feature);
-           //tsn.setConstraint("synonym.name", "'"+qualifier_string+"'");
-           //tsn.addProperty("type_id", lcvterm_id.toString());
+           tsn = new ChadoTransaction(ChadoTransaction.INSERT,
+               alias,
+               feature.getLastModified(), feature);
          }
          sql.add(tsn);
       }
@@ -1075,13 +1233,88 @@ public class ChadoTransactionManager
    */
   private String stripQuotes(String s)
   {
+    if(s == null)
+      return null;
+    
     if(s.startsWith("\"") && s.endsWith("\""))
       s = s.substring(1,s.length()-1);
     
     return s;
   }
 
+  /**
+   * Get the FeatureLoc object
+   * @param feature
+   * @param seg_id
+   * @param range_new
+   * @return
+   */
+  private FeatureLoc getFeatureLoc(GFFStreamFeature feature,
+                             String seg_id, Range range_new)
+  {
+    FeatureLoc featureloc = new FeatureLoc();
+    uk.ac.sanger.artemis.chado.Feature chado_feature = 
+      new uk.ac.sanger.artemis.chado.Feature();
+    chado_feature.setUniquename(seg_id);
+    
+    featureloc.setFeature(chado_feature);
+    featureloc.setFmax(range_new.getEnd());
+    featureloc.setFmin(range_new.getStart()-1);
+    
+    if(feature.getFeature_relationship_rank_store() != null)
+    {
+      Hashtable rank_hash = feature.getFeature_relationship_rank_store();
+      if(rank_hash.containsKey(seg_id))
+      {
+        Integer rank = (Integer)rank_hash.get(seg_id);
+        featureloc.setRank(rank.intValue());
+      }
+      else
+        featureloc.setRank(0);
+    }
+    else
+      featureloc.setRank(0);
+    
+    boolean is_complement = feature.getLocation().isComplement();
+    if(is_complement)
+      featureloc.setStrand(-1);
+    else
+      featureloc.setStrand(1);
+    
+    Qualifier qualifier_phase = feature.getQualifierByName("codon_start");
+    if(qualifier_phase != null)
+    {
+      String phase = (String)(qualifier_phase.getValues()).elementAt(0);
 
+      if(phase.equals ("1"))
+        featureloc.setPhase(0);
+      else if(phase.equals("2"))
+        featureloc.setPhase(1);
+      else if(phase.equals("3")) 
+        featureloc.setPhase(2);
+    }
+    
+    return featureloc;
+  }
+  
+  private FeatureProp getFeatureProp(final String uniquename,
+                                     final String qualifier_string,
+                                     final Long lcvterm_id, 
+                                     final int rank)
+  {
+    FeatureProp featureprop = new FeatureProp();
+    uk.ac.sanger.artemis.chado.Feature chado_feature   = 
+      new uk.ac.sanger.artemis.chado.Feature();
+    chado_feature.setUniquename(uniquename);
+    Cvterm cvterm = new Cvterm();
+    cvterm.setCvtermId(lcvterm_id.longValue());
+    featureprop.setValue(stripQuotes(qualifier_string));
+    featureprop.setRank(rank);
+    featureprop.setCvterm(cvterm);
+    featureprop.setFeature(chado_feature);
+    return featureprop;
+  }
+  
   /**
    *  Invoked when a deletion or insertion occurs in a Bases object.
    **/
diff --git a/uk/ac/sanger/artemis/chado/FeatureDbxref.java b/uk/ac/sanger/artemis/chado/FeatureDbxref.java
index bc4ecd83f8f4fc6c65a128aa07d6bb18eae4843a..54b5576dd9957b815b6d27ebf02ec248c8199090 100644
--- a/uk/ac/sanger/artemis/chado/FeatureDbxref.java
+++ b/uk/ac/sanger/artemis/chado/FeatureDbxref.java
@@ -28,23 +28,21 @@ package uk.ac.sanger.artemis.chado;
  * Representation of the chado feature_dbxref.
  */
 public class FeatureDbxref
-{
-  private String schema;
-  
+{ 
   /** feature_dbxref */
-  private int feature_id;
+  private Feature feature;
   private int dbxref_id;
   private boolean current = true;
   private Dbxref dbxref;
 
-  public int getFeature_id()
+  public Feature getFeature()
   {
-    return feature_id;
+    return feature;
   }
 
-  public void setFeature_id(int feature_id)
+  public void setFeature(Feature feature)
   {
-    this.feature_id = feature_id;
+    this.feature = feature;
   }
 
   public boolean isCurrent()
@@ -57,15 +55,6 @@ public class FeatureDbxref
     this.current = current;
   }
 
-  public String getSchema()
-  {
-    return schema;
-  }
-
-  public void setSchema(String schema)
-  {
-    this.schema = schema;
-  }
 
   public int getDbxref_id()
   {
diff --git a/uk/ac/sanger/artemis/chado/FeatureLoc.java b/uk/ac/sanger/artemis/chado/FeatureLoc.java
index c329b5b3ca475e7f1f37c3cf90e12add922d5223..ae6dca0215e5fbac7fae9f21a1eff61280d4d7c2 100644
--- a/uk/ac/sanger/artemis/chado/FeatureLoc.java
+++ b/uk/ac/sanger/artemis/chado/FeatureLoc.java
@@ -29,6 +29,8 @@ package uk.ac.sanger.artemis.chado;
  */
 public class FeatureLoc
 {
+  /** CHADO feature */
+  private Feature feature;
   /** id of the parent feature */
   private int srcfeature_id = 0;
   /** start position */
@@ -45,6 +47,10 @@ public class FeatureLoc
   private int locgroup;
   /** Used when a feature has >1 location */
   private int rank;
+  
+  private boolean minPartial;
+
+  private boolean maxPartial;
 
   /**
    * Get the strand. The orientation/directionality of the location. 
@@ -203,4 +209,34 @@ public class FeatureLoc
     this.residue_info = residue_info;
   }
 
+  public Feature getFeature()
+  {
+    return feature;
+  }
+
+  public void setFeature(Feature feature)
+  {
+    this.feature = feature;
+  }
+
+  public boolean isMaxPartial()
+  {
+    return maxPartial;
+  }
+
+  public void setMaxPartial(boolean maxPartial)
+  {
+    this.maxPartial = maxPartial;
+  }
+
+  public boolean isMinPartial()
+  {
+    return minPartial;
+  }
+
+  public void setMinPartial(boolean minPartial)
+  {
+    this.minPartial = minPartial;
+  }
+
 }
\ No newline at end of file
diff --git a/uk/ac/sanger/artemis/chado/FeatureProp.java b/uk/ac/sanger/artemis/chado/FeatureProp.java
index 857aea56743be57a54a2c5539c7794c4be71cc60..121787a98cee7772b98767f43511cd8e7e30e69e 100644
--- a/uk/ac/sanger/artemis/chado/FeatureProp.java
+++ b/uk/ac/sanger/artemis/chado/FeatureProp.java
@@ -29,7 +29,7 @@ package uk.ac.sanger.artemis.chado;
  */
 public class FeatureProp
 {
-  
+  public Feature feature;
   public Cvterm cvterm;
   public String value;
   public int rank;
@@ -93,4 +93,14 @@ public class FeatureProp
   {
     this.rank = rank;
   }
+
+  public Feature getFeature()
+  {
+    return feature;
+  }
+
+  public void setFeature(Feature feature)
+  {
+    this.feature = feature;
+  }
 }
\ No newline at end of file
diff --git a/uk/ac/sanger/artemis/chado/FeatureRelationship.java b/uk/ac/sanger/artemis/chado/FeatureRelationship.java
index 73952055ca7faa1d8a5be293129cfea3715a4b84..47c86993dd25cb6b4faa1382be97d31bcf12f75b 100644
--- a/uk/ac/sanger/artemis/chado/FeatureRelationship.java
+++ b/uk/ac/sanger/artemis/chado/FeatureRelationship.java
@@ -30,9 +30,9 @@ package uk.ac.sanger.artemis.chado;
 public class FeatureRelationship
 {
   
-  public int subject_id;
+  public Feature subject;
   /** id of the parent feature */
-  public int object_id;
+  public Feature object;
   /** cv term of feature relationship (e.g. part_of) */
   public Cvterm cvterm;
   /** Additional notes/comments */
@@ -64,18 +64,18 @@ public class FeatureRelationship
    * Get the parent feature_id.
    * @return the parent feature_id
    */
-  public int getObject_id()
+  public Feature getObject()
   {
-    return object_id;
+    return object;
   }
   
   /**
    * Set the parent feature_id.
    * @param object_id  the parent feature_id
    */
-  public void setObject_id(int object_id)
+  public void setObject(Feature object)
   {
-    this.object_id = object_id;
+    this.object = object;
   }
   
   /**
@@ -102,14 +102,14 @@ public class FeatureRelationship
     this.rank = rank;
   }
   
-  public int getSubject_id()
+  public Feature getSubject()
   {
-    return subject_id;
+    return subject;
   }
   
-  public void setSubject_id(int subject_id)
+  public void setSubject(Feature subject)
   {
-    this.subject_id = subject_id;
+    this.subject = subject;
   }
   
   /**
diff --git a/uk/ac/sanger/artemis/chado/FeatureSynonym.java b/uk/ac/sanger/artemis/chado/FeatureSynonym.java
index 4020a3dd8bd57a50092feb8341e4eee0db1f5405..97b9d3d4044159de51756397171e410164cc1dfe 100644
--- a/uk/ac/sanger/artemis/chado/FeatureSynonym.java
+++ b/uk/ac/sanger/artemis/chado/FeatureSynonym.java
@@ -29,12 +29,9 @@ package uk.ac.sanger.artemis.chado;
  * linked to feature via feature_synonym table.
  */
 public class FeatureSynonym
-{
-  private String schema;
-  private String uniquename;
-  
+{ 
   // feature_synonym
-  private Integer feature_id;
+  private Feature feature;
   private Integer synonym_id;
   private Integer pub_id;
   private boolean current;
@@ -42,34 +39,15 @@ public class FeatureSynonym
   
   private Synonym synonym;
   
-  public String getSchema()
-  {
-    return schema;
-  }
-
-  public void setSchema(String schema)
-  {
-    this.schema = schema;
-  }
-
-  public String getUniquename()
-  {
-    return uniquename;
-  }
-
-  public void setUniquename(String uniquename)
-  {
-    this.uniquename = uniquename;
-  }
 
-  public Integer getFeature_id()
+  public Feature getFeature()
   {
-    return feature_id;
+    return feature;
   }
   
-  public void setFeature_id(Integer feature_id)
+  public void setFeature(Feature feature)
   {
-    this.feature_id = feature_id;
+    this.feature = feature;
   }
 
   public Integer getSynonym_id()
diff --git a/uk/ac/sanger/artemis/chado/IBatisDAO.java b/uk/ac/sanger/artemis/chado/IBatisDAO.java
index 166f39908b47e53781322604afffd39c52ead7ac..dd6ac98c3773e0d0bd45b2c881139e6c91d57e95 100644
--- a/uk/ac/sanger/artemis/chado/IBatisDAO.java
+++ b/uk/ac/sanger/artemis/chado/IBatisDAO.java
@@ -296,85 +296,87 @@ public class IBatisDAO implements ChadoDAO
 //
 // WRITE BACK
 //
+  
   /**
-   *
-   * Update attributes defined by the <code>Transaction</code>.
-   * @param tsn         the <code>Transaction</code>
-   * @return	number of rows changed
-   * @throws SQLException
+   * Merge (update) an already persistent object back to the database (at the end of 
+   * the current transaction, or depending upon flush mode). This method is defined in 
+   * all the DAOs. It's recommended to call it through an appropriate one eg SequenceDaoI
+   *  for FeatureI 
+   * 
+   * @param o The object to merge
+   * @throws SQLException 
    */
-  public int updateAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException 
-  { 
-    return sqlMap.update("updateAttributes", tsn);
+  public void merge(Object o) throws SQLException
+  {
+    if(o instanceof FeatureLoc)
+      sqlMap.update("updateFeatureLoc", o);
+    else if(o instanceof Feature)
+      sqlMap.update("updateFeature", o);
+    else if(o instanceof FeatureProp)
+      sqlMap.update("updateFeatureProp", o);
+    else if(o instanceof FeatureRelationship)
+      sqlMap.update("updateFeatureRelationshipsForSubjectId", o);
   }
-
+  
+  
   /**
-   * Insert attributes defined by the <code>Transaction</code>.
-   * @param tsn         the <code>Transaction</code>
-   * @throws SQLException
+   * Save the object to the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI 
+   * for FeatureI 
+   * @param o The object to store
+   * @throws SQLException 
    */
-  public void insertAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException
+  public void persist(Object o) throws SQLException
   {
-    // get the feature id's
-    List feature_ids = sqlMap.queryForList("getFeatureID", tsn);
-
-    for(int i=0; i<feature_ids.size(); i++)
-    {
-      tsn.setFeature_id( ((Feature)feature_ids.get(i)).getId() );
-      sqlMap.insert("insertAttributes", tsn);
-    }
+    if(o instanceof FeatureProp)
+      sqlMap.insert("insertFeatureProp", o);
+    else if(o instanceof Feature)
+      insertFeature((Feature)o);
+    else if(o instanceof FeatureDbxref)
+      insertFeatureDbxref((FeatureDbxref)o);
+    else if(o instanceof FeatureSynonym)
+      insertFeatureAlias((FeatureSynonym)o);
   }
-
+  
+  
   /**
-   * Delete attributes defined by the <code>Transaction</code>.
-   * @param tsn         the <code>Transaction</code>
-   * @throws SQLException
+   * Remove the object from the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI for 
+   * FeatureI 
+   * @param o The object to delete
    */
-  public void deleteAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException
+  public void delete(Object o) throws SQLException
   {
-    // get the feature id's
-    List feature_ids = sqlMap.queryForList("getFeatureID", tsn);
-
-    for(int i=0; i<feature_ids.size(); i++)
-    {
-      tsn.setFeature_id( ((Feature)feature_ids.get(i)).getId() );
-      sqlMap.delete("deleteAttributes", tsn);
-    }
+    if(o instanceof Feature)
+      sqlMap.delete("deleteFeature", o);
+    else if(o instanceof FeatureProp)
+      sqlMap.delete("deleteFeatureProp", o);
+    else if(o instanceof FeatureDbxref)
+      sqlMap.delete("deleteFeatureDbxref", o);
+    else if(o instanceof FeatureSynonym)
+      deleteFeatureSynonym((FeatureSynonym)o);
   }
 
+
   /**
-   * Insert a feature into the database defined by the <code>Transaction</code>.
-   * @param tsn                 the <code>Transaction</code>
-   * @parma srcfeature_id       the parent feature identifier
+   * Insert a feature into the database defined by the <code>Feature</code>.
+   * @param feature   the feature to insert
    * @throws SQLException
    */
-  public void insertFeature
-                    (final ChadoTransaction tsn,
-                     final String srcfeature_id)
+  private void insertFeature
+                    (final Feature feature)
                      throws SQLException
   {
-    // get the organism id from the srcfeature_id 
-    Feature feature = new Feature();
-    FeatureLoc featureloc = new FeatureLoc();
-    feature.setFeatureloc(featureloc);
-    
-    featureloc.setSrcfeature_id(Integer.parseInt(srcfeature_id));
-    
     Integer organism_id = (Integer)sqlMap.queryForObject("getOrganismID", feature);
 
     //
     // insert feature into feature table
-    Feature chadoFeature = tsn.getChadoFeature();
     Organism organism = new Organism();
     organism.setId(organism_id.intValue());
-    chadoFeature.setOrganism(organism);  
-    sqlMap.insert("insertFeature", chadoFeature);
+    feature.setOrganism(organism);  
+    sqlMap.insert("insertFeature", feature);
 
     //
     // get the current feature_id sequence value
@@ -383,229 +385,114 @@ public class IBatisDAO implements ChadoDAO
 
     //
     // insert feature location into featureloc
-    chadoFeature.getFeatureloc().setSrcfeature_id(Integer.parseInt(srcfeature_id));
-    chadoFeature.setId(feature_id);
-    sqlMap.insert("insertFeatureLoc", chadoFeature);
+    feature.setId(feature_id);
+    sqlMap.insert("insertFeatureLoc", feature);
     
-    // insert feature relationship
-    if(tsn.getParents() != null || 
-       tsn.getDerives_from() != null)
+    // insert feature relationships
+    if(feature.getFeatureRelationshipsForSubjectId() != null)
     {
-      List feature_ids = sqlMap.queryForList("getFeatureID", tsn);
+      List parents = feature.getFeatureRelationshipsForSubjectId();
       
-      for(int i=0; i<feature_ids.size(); i++)
+      for(int i=0; i<parents.size(); i++)
       {
         FeatureRelationship feature_relationship =
-              new FeatureRelationship();
-        feature_relationship.setObject_id( ((Feature)feature_ids.get(i)).getId() );
-        feature_relationship.setSubject_id(feature_id);
-        
-        Cvterm cvterm = new Cvterm();
-        if(tsn.getParents().contains( 
-            ((Feature)feature_ids.get(i)).getUniquename() ))
-          cvterm.setName("part_of");
-        else
-          cvterm.setName("derives_from");
-          
-        feature_relationship.setCvterm(cvterm);
-        chadoFeature.setFeature_relationship(feature_relationship);
-        sqlMap.insert("insertFeatureRelationship", chadoFeature);
+               (FeatureRelationship)parents.get(i);
+        sqlMap.insert("insertFeatureRelationship", feature_relationship);
       }
-   
     }
   }
 
-
   /**
-   * Delete a feature from the database defined by the <code>Transaction</code>.
-   * @param tsn         the <code>Transaction</code>
-   * @return    number of rows deleted
+   * Insert a feature_dbxref for a feature.
+   * @param feature_dbxref    the <code>FeatureDbxref</code>
    * @throws SQLException
    */
-  public int deleteFeature
-                    (final ChadoTransaction tsn)
+  private void insertFeatureDbxref(final FeatureDbxref feature_dbxref)
                      throws SQLException
   {
-    Feature chadoFeature = new Feature();
-    chadoFeature.setUniquename(tsn.getUniqueName());
-
-    return sqlMap.delete("deleteFeature", chadoFeature);
-  }
+    Integer db_id = (Integer)sqlMap.queryForObject("getDbId", 
+                         feature_dbxref.getDbxref().getDb());
+    
+    System.out.print(db_id.intValue());
 
-  /**
-   * Insert a dbxref for a feature.
-   * @param tsn           the <code>Transaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public int insertFeatureDbxref(final ChadoTransaction tsn)
-                     throws SQLException
-  {
-    FeatureDbxref dbxref = tsn.getFeatureDbxref();
     
-    Integer db_id = (Integer)sqlMap.queryForObject("getDbId", 
-                                 dbxref.getDbxref().getDb());
     if(db_id == null)
       throw new SQLException("No database called "+
-                             dbxref.getDbxref().getDb().getName()+" found (for "+
-                             tsn.getUniqueName()+
-                             ") check the spelling!");
+          feature_dbxref.getDbxref().getDb().getName()+" found (for "+
+          feature_dbxref.getFeature().getUniquename()+
+          ") check the spelling!");
     
-    dbxref.getDbxref().setDb_id(db_id.intValue());
+    feature_dbxref.getDbxref().setDb_id(db_id.intValue());
     
-    Integer dbxref_id = (Integer)sqlMap.queryForObject("getDbxrefId", dbxref.getDbxref());
+    Integer dbxref_id = 
+      (Integer)sqlMap.queryForObject("getDbxrefId", feature_dbxref.getDbxref());
     if(dbxref_id == null)
     {
       // create a new accession entry in dbxref
-      sqlMap.insert("insertDbxref", dbxref.getDbxref());
+      sqlMap.insert("insertDbxref", feature_dbxref.getDbxref());
       // now get the new dbxref_id
-      dbxref_id = (Integer)sqlMap.queryForObject("getDbxrefId", dbxref.getDbxref());
+      dbxref_id = (Integer)sqlMap.queryForObject("getDbxrefId", 
+          feature_dbxref.getDbxref());
     }
     
-    dbxref.setDbxref_id(dbxref_id.intValue());
-    
-    //  get the feature id's
-    List feature_ids = sqlMap.queryForList("getFeatureID", tsn);
-    dbxref.setFeature_id( ((Feature)feature_ids.get(0)).getId() );
+    feature_dbxref.setDbxref_id(dbxref_id.intValue());
     
-    sqlMap.insert("insertFeatureDbxref", dbxref);
+    //  get the feature id's  
+    Feature feature = getFeatureByUniqueName(
+        feature_dbxref.getFeature().getUniquename());
+    feature_dbxref.getFeature().setId( feature.getId() );
 
-    return 1;
+    sqlMap.insert("insertFeatureDbxref", feature_dbxref);
   }
   
-  /**
-   * Delete a dbxref for a feature.
-   * @param tsn           the <code>Transaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public int deleteFeatureDbxref(final ChadoTransaction tsn)
-                     throws SQLException
-  {
-    FeatureDbxref dbxref = tsn.getFeatureDbxref();
-    
-    // get the feature id's
-    List feature_ids = sqlMap.queryForList("getFeatureID", tsn);
-    
-    dbxref.setFeature_id( ((Feature)feature_ids.get(0)).getId() );
-    return sqlMap.delete("deleteFeatureDbxref", dbxref);
-  }
   
   /**
-   * Insert a synonym for a feature.
-   * @param tsn           the <code>Transaction</code>
-   * @return    number of rows changed
+   * Insert a feature_synonym for a feature.
+   * @param feature_synonym    the <code>FeatureSynonym</code>
    * @throws SQLException
    */
-  public int insertFeatureAlias(final ChadoTransaction tsn)
+  private void insertFeatureAlias(final FeatureSynonym feature_synonym)
                      throws SQLException
   {
-    final FeatureSynonym alias = tsn.getAlias();
-    
     Synonym synonym  = 
       (Synonym)sqlMap.queryForObject("getSynonymByNameAndType", 
-          alias.getSynonym());
+          feature_synonym.getSynonym());
     
     if(synonym == null)
     {
       // create a new synonym name     
-      sqlMap.insert("insertAlias", alias);
+      sqlMap.insert("insertAlias", feature_synonym);
       
       synonym  =
         (Synonym)sqlMap.queryForObject("getSynonymByNameAndType", 
-            alias.getSynonym());
+            feature_synonym.getSynonym());
     }
     
-    alias.setSynonym_id(synonym.getSynonym_id());
-    sqlMap.insert("insertFeatureAlias", alias);
-    return 1;
+    feature_synonym.setSynonym_id(synonym.getSynonym_id());
+    sqlMap.insert("insertFeatureAlias", feature_synonym);
   }
   
   /**
-   * Delete a synonym for a feature.
-   * @param tsn           the <code>Transaction</code>
-   * @return    number of rows changed
+   * Delete a feature_synonym for a feature.
+   * @param feature_synonym     the <code>FeatureSynonym</code>
    * @throws SQLException
    */
-  public int deleteFeatureAlias(final ChadoTransaction tsn)
+  private int deleteFeatureSynonym(final FeatureSynonym feature_synonym)
                      throws SQLException
   {
-    final FeatureSynonym alias = tsn.getAlias();
-     
     List feature_synonym_list = 
-      sqlMap.queryForList("getFeatureSynonymsByName", alias.getSynonym());
+      sqlMap.queryForList("getFeatureSynonymsByName", feature_synonym.getSynonym());
     
     final FeatureSynonym synonym = 
       (FeatureSynonym)feature_synonym_list.get(0); 
-    alias.setSynonym_id(synonym.getSynonym().getSynonym_id());
+    feature_synonym.setSynonym_id(synonym.getSynonym().getSynonym_id());
     
     // check this name is not used some where else, 
     // i.e. in more than one row
     if(feature_synonym_list.size() > 1)
-      return sqlMap.delete("deleteFeatureAlias", alias);
-    else
-      return sqlMap.delete("deleteAlias", alias);
-  }
-  
-  /**
-   * Update feature_relationship for a feature.
-   * @param tsn           the <code>Transaction</code>
-   * @return    number of rows changed
-   * @throws SQLException
-   */
-  public void updateFeatureRelationshipsForSubjectId(
-      final ChadoTransaction tsn)
-                     throws SQLException
-  { 
-    sqlMap.update("updateFeatureRelationshipsForSubjectId", tsn);
-  }
-  
-  /**
-   * Write the time a feature was last modified
-   * @param uniquename  the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @return  number of rows changed
-   * @throws SQLException
-   */
-  public int writeTimeLastModified
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException
-  {
-    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
-                                                uniquename, "feature", 
-                                                null, null);
-    if(timestamp == null)
-      tsn.addProperty("timelastmodified", "CURRENT_TIMESTAMP");
+      return sqlMap.delete("deleteFeatureAlias", feature_synonym);
     else
-      tsn.addProperty("timelastmodified", "'"+ timestamp.toString() + "'");
-    
-    return updateAttributes(tsn);
-  }
-
-  /**
-   * Write the time a feature was last accessed
-   * @param uniquename  the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @return  number of rows changed
-   * @throws SQLException
-   */
-  public int writeTimeAccessioned
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException
-  {
-    ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
-                                                uniquename, "feature", 
-                                                null, null);
-    if(timestamp == null)
-      tsn.addProperty("timelastmodified", "CURRENT_TIMESTAMP");
-    else
-      tsn.addProperty("timelastmodified", "'"+ timestamp.toString() + "'");
-    
-    return updateAttributes(tsn);
+      return sqlMap.delete("deleteAlias", feature_synonym);
   }
   
   public void startTransaction() throws SQLException
@@ -647,7 +534,9 @@ public class IBatisDAO implements ChadoDAO
 
       if(i < feature_size - 1)
         featNext = (Feature)list.get(i + 1);
-
+      else
+        featNext = null;
+      
       // merge next line if part of the same feature
       while(featNext != null && featNext.getUniquename().equals(name))
       {
@@ -679,7 +568,7 @@ public class IBatisDAO implements ChadoDAO
     for(int i = 0; i < list.size(); i++)
     {
       FeatureDbxref dbxref = (FeatureDbxref)list.get(i);
-      Integer feature_id = new Integer(dbxref.getFeature_id());
+      Integer feature_id = new Integer(dbxref.getFeature().getId());
       String value = dbxref.getDbxref().getDb().getName() + ":" + 
                      dbxref.getDbxref().getAccession();
       if(dbxrefHash.containsKey(feature_id))
@@ -698,7 +587,4 @@ public class IBatisDAO implements ChadoDAO
     return dbxrefHash;
   }
 
-
-
 }
-
diff --git a/uk/ac/sanger/artemis/chado/JdbcDAO.java b/uk/ac/sanger/artemis/chado/JdbcDAO.java
index 6758a870a76bd62816e6fa35a5ebcfd19ee3836c..52d5519a57266e2aca722fa523c89da00854c28a 100644
--- a/uk/ac/sanger/artemis/chado/JdbcDAO.java
+++ b/uk/ac/sanger/artemis/chado/JdbcDAO.java
@@ -238,7 +238,10 @@ public class JdbcDAO
       cvterm = new Cvterm();
       cvterm.setCvtermId(rs.getLong("relation_type_id"));
       feature_relationship.setCvterm(cvterm);
-      feature_relationship.setObject_id( rs.getInt("object_id") );
+      
+      Feature object = new Feature();
+      object.setId( rs.getInt("object_id") );
+      feature_relationship.setObject( object  );
       feature.setFeature_relationship(feature_relationship);
   
       // feature organism
@@ -419,8 +422,10 @@ public class JdbcDAO
       db.setName( rs.getString("name") );
       dbxref.setAccession( rs.getString("accession") );
       dbxref.setDb(db);
+      Feature feat = new Feature();
+      feat.setId( rs.getInt("feature_id") );
       feature_dbxref.setDbxref(dbxref);
-      feature_dbxref.setFeature_id( rs.getInt("feature_id") );
+      feature_dbxref.setFeature(feat);
       dbxrefs.add(feature_dbxref);
     }
 
@@ -459,9 +464,11 @@ public class JdbcDAO
       Synonym syn = new Synonym();
       syn.setName(rs.getString("name"));
       syn.setCvterm(cvterm);
-
+      Feature feat = new Feature();
+      feat.setId(rs.getInt("feature_id"));
+      
       alias.setSynonym(syn);
-      alias.setFeature_id(new Integer(rs.getInt("feature_id")));
+      alias.setFeature(feat);
       alias.setPub_id(new Integer(rs.getInt("pub_id")));
       alias.setInternal(rs.getBoolean("is_internal"));
       alias.setCurrent(rs.getBoolean("is_current"));
@@ -487,176 +494,231 @@ public class JdbcDAO
 //
 // WRITE 
 //
+  
+  
   /**
-   * Update attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
-   * @return    number of rows changed
+   * Merge (update) an already persistent object back to the database 
+   * (at the end of the current transaction, or depending upon flush mode). 
+   * This method is defined in all the DAOs. It's recommended to call it 
+   * through an appropriate one eg SequenceDaoI for FeatureI 
+   * @param o The object to merge
+   */
+  public void merge(Object o) throws SQLException
+  {
+    if(o instanceof FeatureLoc)
+      updateFeatureLoc((FeatureLoc)o);
+    else if(o instanceof Feature)
+      updateFeature((Feature)o);
+    else if(o instanceof FeatureProp)
+      updateFeatureProp((FeatureProp)o);
+    else if(o instanceof FeatureRelationship)
+      updateFeatureRelationship((FeatureRelationship)o);
+  }
+  
+  /**
+   * Save the object to the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI 
+   * for FeatureI 
+   * @param o The object to store
+   */
+  public void persist(Object o) throws SQLException
+  {
+    if(o instanceof FeatureProp)
+      insertFeatureProp((FeatureProp)o);
+    else if(o instanceof Feature)
+      insertFeature((Feature)o);
+    else if(o instanceof FeatureDbxref)
+      insertFeatureDbxref((FeatureDbxref)o);
+    else if(o instanceof FeatureSynonym)
+      insertFeatureAlias((FeatureSynonym)o);
+  }
+  
+  /**
+   * Remove the object from the database (at the end of the current transaction, 
+   * or depending upon flush mode). This method is defined in all the DAOs. 
+   * It's recommended to call it through an appropriate one eg SequenceDaoI for 
+   * FeatureI 
+   * @param o The object to delete
+   */
+  public void delete(Object o) throws SQLException
+  {
+    if(o instanceof Feature)
+      deleteFeature((Feature)o);
+    else if(o instanceof FeatureProp)
+      deleteFeatureProp((FeatureProp)o);
+    else if(o instanceof FeatureDbxref)
+      deleteFeatureDbxref((FeatureDbxref)o);
+    else if(o instanceof FeatureSynonym)
+      deleteFeatureSynonym((FeatureSynonym)o);
+  }
+  
+  
+  /**
+   * Update a feature location with the give <code>FeatureLoc</code>
+   * object.
+   * @param featureloc  the new <code>FeatureLoc</code> object.
    * @throws SQLException
    */
-  public int updateAttributes
-                    (final ChadoTransaction tsn)
-                     throws SQLException
+  private void updateFeatureLoc(FeatureLoc featureloc) 
+          throws SQLException
   {
-    List uniquename = tsn.getUniquename();
-    
-    StringBuffer sqlBuff = new StringBuffer();
-    String chadoTable    = tsn.getChadoTable();
-    sqlBuff.append("UPDATE "+chadoTable);
-    sqlBuff.append(" SET ");
-
-    List properties = tsn.getProperties();
-    for(int i=0; i<properties.size(); i++)
-    {
-      sqlBuff.append((String)properties.get(i));
-      if(i < properties.size()-1)
-        sqlBuff.append(" , ");
-    }
+    final String sql = "UPDATE featureloc SET fmin=?, fmax=?, rank=?, strand=?, phase=? "+
+                       "WHERE feature_id=(SELECT feature_id FROM feature WHERE uniquename=?)";
 
-    sqlBuff.append(" FROM feature");
-    sqlBuff.append(" WHERE feature.feature_id="+
-                           chadoTable+".feature_id AND (");
+    PreparedStatement pstmt = conn.prepareStatement(sql);
+    pstmt.setInt(1, featureloc.getFmin());
+    pstmt.setInt(2, featureloc.getFmax());
+    pstmt.setInt(3, featureloc.getRank());
+    pstmt.setInt(4, featureloc.getStrand());
+    pstmt.setInt(5, featureloc.getPhase());
+    pstmt.setString(6, featureloc.getFeature().getUniquename());
+    appendToLogFile(sql, sqlLog);
+    
+    pstmt.executeUpdate();
+  }
+  
+  /**
+   * Update a feature with a given <code>Feature</code> object.
+   * @param feature the new <code>Feature</code> object.
+   * @throws SQLException
+   */
+  private void updateFeature(Feature feature) 
+          throws SQLException
+  {
+    String sql = "UPDATE feature SET uniquename=?";
 
+    if(feature.getCvterm() != null)
+      sql = sql+", type_id=?";
+    
+    if(feature.getTimelastmodified() != null)
+      sql = sql+", timelastmodified=?";
 
-    for(int i=0; i<uniquename.size(); i++)
+    sql = sql+"WHERE feature_id=?";
+    
+    PreparedStatement pstmt = conn.prepareStatement(sql);
+    pstmt.setString(1, feature.getUniquename());
+    int param = 2;
+    if(feature.getCvterm() != null)
     {
-      sqlBuff.append(" feature.uniquename='" + 
-                     (String)uniquename.get(i) +"' ");
-      if(i < uniquename.size()-1)
-        sqlBuff.append("OR");
+      pstmt.setLong(param, feature.getCvterm().getCvtermId());
+      param++;
     }
-
-    sqlBuff.append(")");
-
-    List constraints = tsn.getConstraint();
-    if(constraints != null)
+    
+    if(feature.getTimelastmodified() != null)
     {
-      for(int i=0; i<constraints.size(); i++)
-      {
-        sqlBuff.append(" AND ");
-        // looks like specifying table, so include schema
-        String constraint = (String)constraints.get(i);
-        /*
-        int index;
-        if( (index = constraint.indexOf(".")) > -1 &&
-            constraint.indexOf("=") > index)
-         sqlBuff.append(schema+".");
-        */
-        sqlBuff.append(constraint);
-      }
+      pstmt.setTimestamp(param, 
+          feature.getTimelastmodified());
+      param++;
     }
+    
+    pstmt.setInt(param, feature.getId());
+    appendToLogFile(sql, sqlLog);
+    pstmt.executeUpdate();
+  }
+  
+  /**
+   * Update a feature property with a given <code>FeatureProp</code>
+   * object.
+   * @param featureprop the new <code>FeatureProp</code> object.
+   * @throws SQLException
+   */
+  private void updateFeatureProp(FeatureProp featureprop) 
+          throws SQLException
+  { 
+    String sql = "UPDATE featureprop SET value=? "+
+                 "WHERE rank=? AND type_id=? AND "+
+                 "feature_id=(SELECT feature_id FROM feature WHERE uniquename=?)";
 
-    String sql = sqlBuff.toString();
-
+    PreparedStatement pstmt = conn.prepareStatement(sql);
+    pstmt.setString(1,featureprop.getValue());
+    pstmt.setInt(2,featureprop.getRank());
+    pstmt.setLong(3, featureprop.getCvterm().getCvtermId());
+    pstmt.setString(4, featureprop.getFeature().getUniquename());
+    
     appendToLogFile(sql, sqlLog);
-    Statement st = conn.createStatement();
-    return st.executeUpdate(sql);
+    pstmt.executeUpdate();
   }
+  
 
   /**
-   * Insert attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
+   * Insert attributes defined by the <code>FeatureProp</code>.
+   * @param featureprop     the new <code>FeatureProp</code>
    * @throws SQLException
    */
-  public void insertAttributes
-                    (final ChadoTransaction tsn)
+  private void insertFeatureProp
+                    (final FeatureProp featureprop)
                      throws SQLException
   {
-    StringBuffer sqlBuff;
-
-    List uniquename = tsn.getUniquename();
-    String chadoTable   = tsn.getChadoTable();
-    for(int i=0; i<uniquename.size(); i++)
-    {
-      sqlBuff = new StringBuffer();
-      sqlBuff.append("INSERT INTO "+chadoTable);
-      StringBuffer sqlKeys   = new StringBuffer();
-      StringBuffer sqlValues = new StringBuffer();
-
-      sqlKeys.append("feature_id , ");
-      sqlValues.append("(SELECT feature_id FROM feature WHERE uniquename='"+
-                         (String)uniquename.get(i)+"') , ");
-
-      String name;
+    StringBuffer sqlBuff = new StringBuffer();
 
-      List propertiesName  = tsn.getPropertiesName();
-      List propertiesValue = tsn.getPropertiesValue();
-      for(int j=0; j<propertiesName.size(); j++)
-      {
-        name = (String)propertiesName.get(j);
-        sqlKeys.append(name);
-        sqlValues.append((String)propertiesValue.get(j));
-        if(j < propertiesName.size()-1)
-        {
-          sqlKeys.append(" , ");
-          sqlValues.append(" , ");
-        }
-      }
-  
-      sqlBuff.append(" ( "+sqlKeys.toString()+" ) ");
-      sqlBuff.append(" values ");
-      sqlBuff.append(" ( "+sqlValues.toString()+" )");
+    sqlBuff.append("INSERT INTO featureprop");
+    sqlBuff.append(" ( feature_id, type_id, value, rank ) ");
+    sqlBuff.append("VALUES ");
+    
+    sqlBuff.append("((SELECT feature_id FROM feature WHERE uniquename=");
+    sqlBuff.append("'"+ featureprop.getFeature().getUniquename()+"')," );
+    sqlBuff.append(featureprop.getCvterm().getCvtermId()+", ");
+    sqlBuff.append(featureprop.getValue()+",");
+    sqlBuff.append(featureprop.getRank());
 
-      appendToLogFile(new String(sqlBuff), sqlLog);
+    appendToLogFile(new String(sqlBuff), sqlLog);
 
-      Statement st = conn.createStatement();
-      int rowCount = st.executeUpdate(new String(sqlBuff));
-      System.out.println(rowCount+" row(s) inserted");
-    }
+    Statement st = conn.createStatement();
+    int rowCount = st.executeUpdate(new String(sqlBuff));
+    System.out.println(rowCount + " row(s) inserted");
   }
 
   /**
-   * Delete attributes defined by the <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
+   * Delete attributes defined by the <code>FeatureProp</code>.
+   * @param featureprop      the new <code>FeatureProp</code>
    * @throws SQLException
    */
-  public void deleteAttributes
-                    (final ChadoTransaction tsn)
+  private void deleteFeatureProp
+                    (final FeatureProp featureprop)
                      throws SQLException
   {
-    StringBuffer sqlBuff;
-
-    List uniquename = tsn.getUniquename();
-    String chadoTable   = tsn.getChadoTable();
-    for(int i=0; i<uniquename.size(); i++)
-    {
-      sqlBuff = new StringBuffer();
+    StringBuffer sqlBuff = new StringBuffer();
+    String uniquename = featureprop.getFeature().getUniquename();
 
-      sqlBuff.append("DELETE FROM "+chadoTable+" WHERE ");
+    sqlBuff.append("DELETE FROM featureprop WHERE ");
 
-      List constraints = tsn.getConstraint();
-      for(int j=0; j<constraints.size(); j++)
-        sqlBuff.append((String)constraints.get(j)+" AND ");
+    if(uniquename != null)
+      sqlBuff.append("feature_id="+
+          "(SELECT feature_id FROM feature WHERE uniquename='"+
+          uniquename+"') AND ");
+    
+    if(featureprop.getRank() > -1)
+      sqlBuff.append("rank="+featureprop.getRank()+" AND ");
+    
+    if(featureprop.getValue() != null)
+      sqlBuff.append("value="+featureprop.getValue()+" AND ");
+    
+    sqlBuff.append("type_id="+featureprop.getCvterm().getCvtermId());
       
-      sqlBuff.append("feature_id=(SELECT feature_id FROM "+
-                     "feature WHERE uniquename='"+
-                     (String)uniquename.get(i)+"')");
-
-      System.out.println(sqlBuff.toString());
-      appendToLogFile(new String(sqlBuff), sqlLog);
+    appendToLogFile(new String(sqlBuff), sqlLog);
 
-      Statement st = conn.createStatement();
-      int rowCount = st.executeUpdate(new String(sqlBuff));
-      System.out.println(rowCount+" row(s) deleted");
-    }
+    Statement st = conn.createStatement();
+    int rowCount = st.executeUpdate(new String(sqlBuff));
+    System.out.println(rowCount+" row(s) deleted");
   }
 
 
   /**
-   * Insert a feature into the database defined by the <code>ChadoTransaction</code>.
-   * @param tsn                 the <code>ChadoTransaction</code>
-   * @parma srcfeature_id       the parent feature identifier
+   * Insert a feature into the database defined by the <code>Feature</code>.
+   * @param feature    the new <code>Feature</code>
    * @throws SQLException
    */
-  public void insertFeature
-                    (final ChadoTransaction tsn, 
-                     final String srcfeature_id)
+  private void insertFeature
+                    (final Feature feature)
                      throws SQLException
   {
     //
     // get the organism_id
     Statement st = conn.createStatement();
     String sql = "SELECT organism_id from " +
-                 "feature where feature_id = '" + srcfeature_id + "'";
+                 "feature where feature_id = '" + 
+                 feature.getFeatureloc().getSrcfeature_id() + "'";
 
     appendToLogFile(sql, sqlLog);
     ResultSet rs = st.executeQuery(sql);
@@ -664,7 +726,6 @@ public class JdbcDAO
 
     final int organism_id = rs.getInt("organism_id");
 
-    Feature chadoFeature = tsn.getChadoFeature();
     // insert new feature into feature table
     StringBuffer sql_buff = new StringBuffer();
     sql_buff.append("INSERT INTO feature (");
@@ -676,9 +737,9 @@ public class JdbcDAO
     sql_buff.append(" ) VALUES ( ");
     sql_buff.append("nextval('feature_feature_id_seq') , ");
     sql_buff.append(organism_id+" , ");
-    sql_buff.append("'"+chadoFeature.getName()+"'"+" , ");
-    sql_buff.append("'"+chadoFeature.getUniquename()+"'"+" , ");
-    sql_buff.append(Long.toString(chadoFeature.getCvterm().getCvtermId()));
+    sql_buff.append("'"+feature.getName()+"'"+" , ");
+    sql_buff.append("'"+feature.getUniquename()+"'"+" , ");
+    sql_buff.append(Long.toString(feature.getCvterm().getCvtermId()));
     sql_buff.append(" )");
 
     sql = new String(sql_buff);
@@ -709,32 +770,61 @@ public class JdbcDAO
     sql_buff.append(" ) VALUES ( ");
     sql_buff.append("nextval('featureloc_featureloc_id_seq') , ");
     sql_buff.append(feature_id+" , ");
-    sql_buff.append(srcfeature_id+" , ");
-    sql_buff.append(chadoFeature.getFeatureloc().getFmin()+" , ");
-    sql_buff.append(chadoFeature.getFeatureloc().getFmax()+" , ");
-    sql_buff.append(chadoFeature.getFeatureloc().getStrand()+" , ");
-    sql_buff.append(chadoFeature.getFeatureloc().getPhase());
+    sql_buff.append(feature.getFeatureloc().getSrcfeature_id()+" , ");
+    sql_buff.append(feature.getFeatureloc().getFmin()+" , ");
+    sql_buff.append(feature.getFeatureloc().getFmax()+" , ");
+    sql_buff.append(feature.getFeatureloc().getStrand()+" , ");
+    sql_buff.append(feature.getFeatureloc().getPhase());
     sql_buff.append(" )");
 
     sql = new String(sql_buff);
     appendToLogFile(sql, sqlLog);
     st = conn.createStatement();
     rowCount = st.executeUpdate(sql);
+    
+    
+//  insert feature relationships
+    if(feature.getFeatureRelationshipsForSubjectId() != null)
+    {
+      List parents = feature.getFeatureRelationshipsForSubjectId();
+      for(int i=0; i<parents.size(); i++)
+      {
+        // insert feature_relationship
+        FeatureRelationship feature_relationship =
+               (FeatureRelationship)parents.get(i);
+        
+        sql_buff = new StringBuffer();
+        sql_buff.append("INSERT INTO feature_relationship ");
+        sql_buff.append("( subject_id, object_id, type_id ) ");
+        sql_buff.append("VALUES ");
+        sql_buff.append("( (SELECT feature_id FROM feature WHERE uniquename='");
+        sql_buff.append(feature_relationship.getSubject().getUniquename()+"'), ");
+        sql_buff.append("(SELECT feature_id FROM feature WHERE uniquename='");
+        sql_buff.append(feature_relationship.getObject().getUniquename()+"'), ");
+        sql_buff.append(feature_relationship.getCvterm().getCvtermId()+")");
+        
+        sql = new String(sql_buff);
+        appendToLogFile(sql, sqlLog);
+        st = conn.createStatement();
+        rowCount = st.executeUpdate(sql);
+        
+      }
+    }
+
   }
 
   /**
    * Delete a feature from the database defined by the 
-   * <code>ChadoTransaction</code>.
-   * @param tsn         the <code>ChadoTransaction</code>
-   * @return	number of rows deleted
+   * <code>Feature</code>.
+   * @param feature  the new <code>Feature</code>
    * @throws SQLException
    */
-  public int deleteFeature
-                    (final ChadoTransaction tsn)
+  private int deleteFeature
+                    (final Feature feature)
                      throws SQLException
   {
     String sql = "DELETE FROM feature WHERE uniquename='"+
-                 tsn.getUniqueName()+"'";
+                 feature.getUniquename()+"'";
     appendToLogFile(sql, sqlLog);
     
     Statement st = conn.createStatement();
@@ -742,20 +832,16 @@ public class JdbcDAO
   }
 
   /**
-   * Insert a dbxref for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
+   * Insert a feature_dbxref for a feature.
+   * @param feature_dbxref    the new <code>FeatureDbxref</code>
    * @throws SQLException
    */
-  public int insertFeatureDbxref(final ChadoTransaction tsn)
+  private void insertFeatureDbxref(final FeatureDbxref feature_dbxref)
                      throws SQLException
-  {
-    final FeatureDbxref dbxref = tsn.getFeatureDbxref();
-    final String uniquename  = tsn.getUniqueName();
-    
+  {   
     // find database id
     String sql = "SELECT db_id FROM db WHERE name='"+
-                 dbxref.getDbxref().getDb().getName()+"'";
+                 feature_dbxref.getDbxref().getDb().getName()+"'";
     
     Statement st   = conn.createStatement();
     ResultSet rs   = st.executeQuery(sql);
@@ -763,14 +849,14 @@ public class JdbcDAO
     
     if(!exists)
       throw new SQLException("No database called "+
-                             dbxref.getDbxref().getDb().getName()+
-                             " found (for "+uniquename+
-                             ") check the spelling!");
+          feature_dbxref.getDbxref().getDb().getName()+
+          " found (for "+feature_dbxref.getFeature().getUniquename()+
+          ") check the spelling!");
 
     final int db_id = rs.getInt("db_id");
     // find if accession exists already
     String sqlDbxrefId = "SELECT dbxref_id FROM dbxref WHERE accession='"+
-                          dbxref.getDbxref().getAccession()+"' AND db_id="+db_id;
+           feature_dbxref.getDbxref().getAccession()+"' AND db_id="+db_id;
     
     appendToLogFile(sqlDbxrefId, sqlLog);
     rs     = st.executeQuery(sqlDbxrefId);
@@ -780,7 +866,7 @@ public class JdbcDAO
     {
       // create a new accession entry in dbxref
       sql = "INSERT INTO dbxref ( db_id, accession ) "+
-            "VALUES ("+db_id+", '"+dbxref.getDbxref().getAccession()+"' )";
+            "VALUES ("+db_id+", '"+feature_dbxref.getDbxref().getAccession()+"' )";
       
       appendToLogFile(sql, sqlLog);
       int rowCount = st.executeUpdate(new String(sql));
@@ -796,49 +882,47 @@ public class JdbcDAO
           "(feature_id, dbxref_id, is_current)"+
           " VALUES "+
           "( (SELECT feature_id FROM "+
-             "feature WHERE  uniquename='"+uniquename+"'), "+
-          dbxref_id+", "+ Boolean.toString(dbxref.isCurrent())+")";
+             "feature WHERE  uniquename='"+feature_dbxref.getFeature().getUniquename()+"'), "+
+          dbxref_id+", "+ Boolean.toString(feature_dbxref.isCurrent())+")";
     System.out.println(sql);
     appendToLogFile(sql, sqlLog);
-    return st.executeUpdate(new String(sql));
+    st.executeUpdate(new String(sql));
   }
   
   /**
-   * Delete a dbxref for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
+   * Delete a feature_dbxref for a feature.
+   * @param feature_dbxref  the  new <code>FeatureDbxref</code>
    * @throws SQLException
    */
-  public int deleteFeatureDbxref(final ChadoTransaction tsn)
+  private void deleteFeatureDbxref(final FeatureDbxref feature_dbxref)
                      throws SQLException
   {
-    final FeatureDbxref dbxref = tsn.getFeatureDbxref();
-    final String uniquename = tsn.getUniqueName();
+    final String uniquename = feature_dbxref.getFeature().getUniquename();
     
     final String sql = 
       "DELETE FROM feature_dbxref "+
       "WHERE dbxref_id="+
-      "(SELECT dbxref_id FROM dbxref WHERE accession='"+dbxref.getDbxref().getAccession()+"' "+
-             "AND db_id=(SELECT db_id FROM db WHERE name='"+dbxref.getDbxref().getDb().getName()+"'))"+
+      "(SELECT dbxref_id FROM dbxref WHERE accession='"+
+         feature_dbxref.getDbxref().getAccession()+"' "+
+      "AND db_id=(SELECT db_id FROM db WHERE name='"+
+         feature_dbxref.getDbxref().getDb().getName()+"'))"+
       "AND feature_id=(SELECT feature_id FROM "+
              "feature WHERE  uniquename='"+uniquename+"')";
     
     Statement st = conn.createStatement();
-    return st.executeUpdate(sql);
+    st.executeUpdate(sql);
   }
   
   /**
-   * Insert a synonym for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
+   * Insert a feature_synonym for a feature.
+   * @param feature_synonym  the new <code>FeatureSynonym</code>
    * @throws SQLException
    */
-  public int insertFeatureAlias(final ChadoTransaction tsn)
+  private void insertFeatureAlias(final FeatureSynonym feature_synonym)
                      throws SQLException
   {
-    final FeatureSynonym alias  = tsn.getAlias();
-    final String uniquename   = alias.getUniquename();
-    final String synonym_name = alias.getSynonym().getName();
+    final String uniquename   = feature_synonym.getFeature().getUniquename();
+    final String synonym_name = feature_synonym.getSynonym().getName();
       
     String sql;
      
@@ -854,7 +938,8 @@ public class JdbcDAO
     if(!exists)
     {
       // create a new synonym name     
-      String type_id = Long.toString(alias.getSynonym().getCvterm().getCvtermId());
+      String type_id =
+        Long.toString(feature_synonym.getSynonym().getCvterm().getCvtermId());
       
       sql = "INSERT INTO "+
             "synonym (name, type_id, synonym_sgml) values ( '"+
@@ -877,21 +962,20 @@ public class JdbcDAO
                " 1)";
  
     appendToLogFile(sql, sqlLog);
-    return st.executeUpdate(sql);
+    st.executeUpdate(sql);
   }
   
   /**
-   * Delete a synonym for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
+   * Delete a feature_synonym for a feature.
+   * @param feature_synonym  the new <code>FeatureSynonym</code>
    * @return    number of rows changed
    * @throws SQLException
    */
-  public int deleteFeatureAlias(final ChadoTransaction tsn)
+  private void deleteFeatureSynonym(final FeatureSynonym feature_synonym)
                      throws SQLException
   {
-    final FeatureSynonym alias = tsn.getAlias();
-    final String uniquename   = alias.getUniquename();
-    final String synonym_name = alias.getSynonym().getName();
+    final String uniquename   = feature_synonym.getFeature().getUniquename();
+    final String synonym_name = feature_synonym.getSynonym().getName();
     String sql = "SELECT synonym_id FROM synonym WHERE "+
                  "synonym.name='"+synonym_name+"'";
     
@@ -916,41 +1000,31 @@ public class JdbcDAO
       sql = "DELETE FROM synonym WHERE synonym_id="+synonym_id;
     
     st   = conn.createStatement();
-    return st.executeUpdate(sql);
+    st.executeUpdate(sql);
   }
   
   /**
    * Update feature_relationship for a feature.
-   * @param tsn           the <code>ChadoTransaction</code>
-   * @return    number of rows changed
+   * @param feature_relationship  the <code>FeatureRelationship</code>
    * @throws SQLException
    */
-  public void updateFeatureRelationshipsForSubjectId(
-      final ChadoTransaction tsn)
+  private void updateFeatureRelationship(
+      final FeatureRelationship feature_relationship)
                      throws SQLException
-  {
-    final Feature chado_feature = tsn.getChadoFeature();
-    final String parent = tsn.getParent_uniquename();
-    
-      
+  {  
     StringBuffer sqlBuff = new StringBuffer();
     sqlBuff.append("UPDATE feature_relationship ");
     sqlBuff.append(" SET ");
-
-    List properties = tsn.getProperties();
-    for(int i=0; i<properties.size(); i++)
-    {
-      sqlBuff.append((String)properties.get(i));
-      if(i < properties.size()-1)
-        sqlBuff.append(" , ");
-    }
-
-    sqlBuff.append(" WHERE feature_relationship.subject_id="+
-        "(SELECT feature_id FROM feature WHERE uniquename='"+
-        chado_feature.getUniquename()+"') AND "+
-        "feature_relationship.object_id="+
-        "(SELECT feature_id FROM feature WHERE uniquename='"+
-        parent+"')"); 
+    sqlBuff.append(" rank="+feature_relationship.getRank()+", ");
+    sqlBuff.append(" type_id="+feature_relationship.getCvterm().getCvtermId());
+    sqlBuff.append(" WHERE ");
+    sqlBuff.append("subject_id=");
+    sqlBuff.append("( SELECT feature_id FROM feature WHERE uniquename='");
+    sqlBuff.append(feature_relationship.getSubject().getUniquename()+"' ) ");
+    sqlBuff.append("AND ");
+    sqlBuff.append("object_id=");
+    sqlBuff.append("( SELECT feature_id FROM feature WHERE uniquename='");
+    sqlBuff.append(feature_relationship.getObject().getUniquename()+"' ) ");
  
     String sql = sqlBuff.toString();
 
@@ -960,79 +1034,7 @@ public class JdbcDAO
     st.executeUpdate(sql);
   }
   
-  /**
-   * Write the time a feature was last modified
-   * @param uniquename  the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @return  number of rows changed
-   * @throws SQLException
-   */
-  public int writeTimeLastModified
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException
-  {
-    String sql = "UPDATE "+
-                 "feature SET timelastmodified=";
-    
-    if(timestamp == null)
-      sql = sql +"CURRENT_TIMESTAMP";
-    else
-      sql = sql +"?";
-      
-    sql = sql + " WHERE uniquename= ?";
-    
-    PreparedStatement pstmt = conn.prepareStatement(sql);
-
-    int param = 1;
-    if(timestamp != null)
-    {
-      pstmt.setTimestamp(param, timestamp);
-      param++;
-    }
-    pstmt.setString(param, uniquename);
-    
-    int rowCount = pstmt.executeUpdate();
-    return rowCount;
-  }
-
-  /**
-   * Write the time a feature was last accessed
-   * @param uniquename  the unique name of the feature
-   * @param timestamp   the time stamp to use, 
-   *                    if NULL use CURRENT_TIMESTAMP
-   * @throws SQLException
-   */
-  public int writeTimeAccessioned
-                    (final String uniquename,
-                     final Timestamp timestamp)
-                     throws SQLException
-  {   
-    String sql = "UPDATE "+
-                 "feature SET timeaccessioned=";
-
-    if(timestamp == null)
-      sql = sql +"CURRENT_TIMESTAMP";
-    else
-      sql = sql +"?";
-
-    sql = sql + " WHERE uniquename= ?";
-
-    PreparedStatement pstmt = conn.prepareStatement(sql);
-
-    int param = 1;
-    if(timestamp != null)
-    {
-      pstmt.setTimestamp(param, timestamp);
-      param++;
-    }
-    pstmt.setString(param, uniquename);
-
-    int rowCount = pstmt.executeUpdate();
-    return rowCount;
-  }
-
+  
   /**
    * Appends a log entry to the log file
    * @param logEntry    entry to add to log file
@@ -1065,9 +1067,7 @@ public class JdbcDAO
         {
           bw.close();
         }
-        catch(IOException ioe2)
-        {
-        }
+        catch(IOException ioe2){}
     }
   }
 
diff --git a/uk/ac/sanger/artemis/util/DatabaseDocument.java b/uk/ac/sanger/artemis/util/DatabaseDocument.java
index a538fbd70f4dab1f6090e9dfdbbf024f97a5c9cb..1f21e457dfabbb3c26422fea6b4e830e394fdbb9 100644
--- a/uk/ac/sanger/artemis/util/DatabaseDocument.java
+++ b/uk/ac/sanger/artemis/util/DatabaseDocument.java
@@ -26,7 +26,6 @@ package uk.ac.sanger.artemis.util;
 
 import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
 import uk.ac.sanger.artemis.io.GFFStreamFeature;
-import uk.ac.sanger.artemis.io.InvalidRelationException;
 import uk.ac.sanger.artemis.io.ReadFormatException;
 import uk.ac.sanger.artemis.chado.*;
 import uk.ac.sanger.artemis.components.DatabaseEntrySource;
@@ -474,11 +473,12 @@ public class DatabaseDocument extends Document
           this_buff = buffers[j];
       }
       
+      
       chadoToGFF(feat, parentFeature.getUniquename(),
                  dbxrefs, synonym,
                  id_store, dao, 
                  feat.getFeatureloc(), this_buff);
-
+       
       if( i%10 == 0 || i == feature_size-1)
         progress_listener.progressMade("Read from database: " + 
                                        feat.getUniquename());
@@ -505,7 +505,7 @@ public class DatabaseDocument extends Document
     for(int i=0; i<list.size(); i++)
     {
       alias = (FeatureSynonym)list.get(i);
-      feature_id = alias.getFeature_id();
+      feature_id = new Integer(alias.getFeature().getId());
       if(synonym.containsKey(feature_id))
         value = (Vector)synonym.get(feature_id);
       else
@@ -571,7 +571,7 @@ public class DatabaseDocument extends Document
     {
       //Feature transcript = new Feature();
       
-      int id = ((FeatureRelationship) relations.get(i)).getSubject_id();
+      int id = ((FeatureRelationship) relations.get(i)).getSubject().getId();
       //transcript.setId(id);
       Feature transcript = dao.getFeatureById(id); //.getLazyFeature(transcript);
 
@@ -588,7 +588,7 @@ public class DatabaseDocument extends Document
 
       for(int j = 0; j < transcipt_relations.size(); j++)
       {
-        id = ((FeatureRelationship) transcipt_relations.get(j)).getSubject_id();
+        id = ((FeatureRelationship) transcipt_relations.get(j)).getSubject().getId();
         //Feature child = new Feature();
         //child.setId(((FeatureRelationship) transcipt_relations.get(j))
         //    .getSubject_id());
@@ -644,7 +644,7 @@ public class DatabaseDocument extends Document
     if(feat.getFeature_relationship() != null)
     {
       FeatureRelationship feat_relationship = feat.getFeature_relationship();
-      parent_id = Integer.toString(feat_relationship.getObject_id());
+      parent_id = Integer.toString(feat_relationship.getObject().getId());
       long parent_type_id = feat_relationship.getCvterm().getCvtermId();
       
       parent_relationship = feat_relationship.getCvterm().getName();
@@ -660,9 +660,9 @@ public class DatabaseDocument extends Document
       {
         FeatureRelationship feat_relationship = 
                             (FeatureRelationship)relations.get(i);
-        parent_id = Integer.toString(feat_relationship.getObject_id());
+        parent_id = Integer.toString(feat_relationship.getObject().getId());
         System.out.println("HERE   "+i+" "+feat_relationship.getCvterm().getName()+ " "+
-            feat_relationship.getObject_id()+" "+feat_relationship.getSubject_id()+ " parent_id="+ parent_id);
+            feat_relationship.getObject().getId()+" "+feat_relationship.getSubject().getId()+ " parent_id="+ parent_id);
         parent_relationship = feat_relationship.getCvterm().getName();
       }
     }
@@ -1033,26 +1033,26 @@ public class DatabaseDocument extends Document
       Vector names_checked = new Vector();
       for(i = 0; i < sql.size(); i++)
       {
-        ChadoTransaction tsn = (ChadoTransaction) sql.get(i);
- 
-        if(tsn.getType() != ChadoTransaction.INSERT_FEATURE ||
-           tsn.getType() != ChadoTransaction.DELETE_FEATURE)
-        {
-          final List uniquename = tsn.getUniquename();
-          
-          for(int j=0; j<uniquename.size(); j++)
-          {
-            if(names_checked.contains((String)uniquename.get(j)))
-              continue;
+        ChadoTransaction tsn = (ChadoTransaction)sql.get(i);
+        if( (tsn.getType() == ChadoTransaction.INSERT ||
+             tsn.getType() == ChadoTransaction.DELETE) && 
+             tsn.getFeatureObject() instanceof Feature )
+          continue;
             
-            names_checked.add((String)uniquename.get(j));
-            unchanged = checkFeatureTimestamp(schema, 
-                           (String)uniquename.get(j), 
+        final String uniquename = tsn.getUniquename();
+        
+        if(uniquename == null)
+          continue;
+        if(names_checked.contains(uniquename))
+          continue;
+            
+        names_checked.add(uniquename);
+        
+        unchanged = checkFeatureTimestamp(schema, 
+                         uniquename, 
                          tsn.getLastModified(), dao);
-            if(!unchanged)
-              return 0;
-          }
-        }
+        if(!unchanged)
+          return 0;
       }  
       
       try
@@ -1067,65 +1067,76 @@ public class DatabaseDocument extends Document
           ChadoTransaction tsn = (ChadoTransaction) sql.get(i);
 
           if(tsn.getType() == ChadoTransaction.UPDATE)
-            dao.updateAttributes(tsn);
+          {
+            if(tsn.getFeatureObject() instanceof Feature)
+            {
+              Feature feature = (Feature)tsn.getFeatureObject();
+              
+              if(feature.getUniquename() != null)
+              {
+                final String uniquename;
+                if(tsn.getOldUniquename() != null)
+                  uniquename = (String)tsn.getOldUniquename();
+                else
+                  uniquename = feature.getUniquename();
+                
+                Feature old_feature
+                    = dao.getFeatureByUniqueName(uniquename);
+                feature.setId( old_feature.getId() );
+                
+                tsn.setOldUniquename(feature.getUniquename());
+              }
+            }
+            dao.merge(tsn.getFeatureObject());
+            //dao.updateAttributes(tsn);
+          }
           else if(tsn.getType() == ChadoTransaction.INSERT)
-            dao.insertAttributes(tsn);
+          {
+            // set srcfeature_id
+            if(tsn.getFeatureObject() instanceof Feature)
+            {
+              FeatureLoc featureloc = ((Feature)tsn.getFeatureObject()).getFeatureloc();
+              featureloc.setSrcfeature_id(Integer.parseInt(feature_id));
+            }
+            dao.persist(tsn.getFeatureObject());
+            //dao.insertAttributes(tsn);
+          }
           else if(tsn.getType() == ChadoTransaction.DELETE)
-            dao.deleteAttributes(tsn);
-          else if(tsn.getType() == ChadoTransaction.INSERT_FEATURE)
-            dao.insertFeature(tsn, feature_id);
-          else if(tsn.getType() == ChadoTransaction.DELETE_FEATURE)
-            dao.deleteFeature(tsn);
-          else if(tsn.getType() == ChadoTransaction.DELETE_DBXREF)
-            dao.deleteFeatureDbxref(tsn);
-          else if(tsn.getType() == ChadoTransaction.INSERT_DBXREF)
-            dao.insertFeatureDbxref(tsn);
-          else if(tsn.getType() == ChadoTransaction.DELETE_ALIAS)
-            dao.deleteFeatureAlias(tsn);
-          else if(tsn.getType() == ChadoTransaction.INSERT_ALIAS)
-            dao.insertFeatureAlias(tsn);
-          else if(tsn.getType() == ChadoTransaction.UPDATE_FEATURE_RELATIONSHIP)
-            dao.updateFeatureRelationshipsForSubjectId(tsn);
+            dao.delete(tsn.getFeatureObject());
         }
 
         //
         // update timelastmodified timestamp
-        Timestamp ts = null;
-        Timestamp ts2;
+        Timestamp ts = new Timestamp(new java.util.Date().getTime());
         names_checked = new Vector();
         for(int j = 0; j < sql.size(); j++)
         {
-          ChadoTransaction tsn = (ChadoTransaction) sql.get(j);
-
-          if(tsn.getType() != ChadoTransaction.INSERT_FEATURE &&
-             tsn.getType() != ChadoTransaction.DELETE_FEATURE)
-          {
-            final List uniquename = tsn.getUniquename();
-
-            // update timelastmodified timestamp
-            for(int k = 0; k < uniquename.size(); k++)
-            {
-              if(names_checked.contains((String) uniquename.get(k)))
-                continue;
-
-              names_checked.add((String) uniquename.get(k));
-
-              dao.writeTimeLastModified((String) uniquename.get(k), ts);
-              
-              Feature feature = dao.getFeatureByUniqueName((String) uniquename.get(k));
-              ts2 = feature.getTimelastmodified();
-              if(ts2 == null)
-                continue;
+          ChadoTransaction tsn = (ChadoTransaction)sql.get(j);
+          
+          if( (tsn.getType() == ChadoTransaction.INSERT ||
+              tsn.getType() == ChadoTransaction.DELETE) && 
+              tsn.getFeatureObject() instanceof Feature )
+           continue;
+          
+          final String uniquename = tsn.getUniquename();
+          if(uniquename == null)
+            continue;
+            
+          if(names_checked.contains(uniquename))
+            continue;
 
-              if(ts == null)
-                ts = ts2;
+          names_checked.add(uniquename);
 
-              GFFStreamFeature gff_feature = (GFFStreamFeature) tsn
-                  .getFeatureObject();
-              
-              gff_feature.setLastModified(ts);
-            }
+          Feature feature = dao.getFeatureByUniqueName(uniquename);
+          if(feature != null)
+          {
+            feature.setTimelastmodified(ts);
+            dao.merge(feature);
           }
+
+          GFFStreamFeature gff_feature = (GFFStreamFeature) tsn
+              .getGff_feature();
+          gff_feature.setLastModified(ts);
         }
         
         if(dao instanceof IBatisDAO && 
@@ -1173,6 +1184,8 @@ public class DatabaseDocument extends Document
                                        throws SQLException
   {
     Feature feature = dao.getFeatureByUniqueName(uniquename);
+    if(feature == null)
+      return true;
     Timestamp now = feature.getTimelastmodified();
     
     if(now != null && timestamp != null)