diff --git a/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadNpcCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadNpcCommand.java
index 2348e1519b983ac0b4448212ac6158e3dd6ba753..8b4169759492cd8e22b2b59b12d8b9447b5ad5ef 100644
--- a/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadNpcCommand.java
+++ b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadNpcCommand.java
@@ -98,23 +98,7 @@ public class LoadNpcCommand extends Command {
             try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) {
                 AetherMudStorage storage = tx.getStorage();
                 NpcData npcData = storage.newNpcData();
-                try {
-                    PropertyUtils.copyProperties(npcData, npc);
-                    PropertyUtils.copyProperties(npcData.createStatsData(), npc.getStats());
-                    PropertyUtils.copyProperties(npcData.createLootData(), npc.getLoot());
-                } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException ex) {
-                    throw new IllegalStateException("Could not copy properties for stats", ex);
-                }
-                npc.getSpawnRules().forEach(new Consumer<SpawnRule>() {
-                    @Override
-                    public void accept(SpawnRule spawnRule) {
-                        try {
-                            PropertyUtils.copyProperties(npcData.createSpawnRuleData(), spawnRule);
-                        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException ex) {
-                            throw new IllegalStateException("Could not copy properties for stats", ex);
-                        }
-                    }
-                });
+                NpcData.copyNpc(npcData, npc);
                 tx.success();
                 write("NPC Saved. - " + npc.getName() + "\r\n");
             }
diff --git a/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java b/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
index 972d3f1cf661c13c69daa5c43667196a7df0be4a..b8e4dbff133cff65ba39d800e8e283d974a33f3f 100644
--- a/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
+++ b/src/main/java/com/syncleus/aethermud/npc/NpcBuilder.java
@@ -85,12 +85,7 @@ public class NpcBuilder {
         this.criticalAttackMessages = Sets.newHashSet(npc.getCriticalAttackMessages());
         this.battleMessages = Sets.newHashSet(npc.getBattleMessages());
         this.idleMessages = Sets.newHashSet(npc.getIdleMessages());
-        this.loot = new Loot();
-        try {
-            PropertyUtils.copyProperties(this.loot, npc.getLoot());
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            throw new IllegalStateException("Could not copy properties");
-        }
+        this.loot = npc.getLoot();
     }
 
     public NpcBuilder setGameManager(GameManager gameManager) {
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java
index db2632426dd8104f7f3c4a033a6e41ad4112dd7b..2bf0f8f09c1bb76371613fb5cf8968c1fb8e57a9 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java
@@ -75,7 +75,12 @@ public class GraphDbAetherMudStorage implements AetherMudStorage {
 
     @Override
     public ItemData saveItem(Item item) {
-        ItemData itemData = framedGraph.addFramedVertex(ItemData.class);
+        Optional<ItemData> existing = this.getItemEntity(item.getItemId());
+        ItemData itemData;
+        if(existing.isPresent())
+            itemData = existing.get();
+        else
+            itemData = framedGraph.addFramedVertex(ItemData.class);
         ItemData.copyItem(itemData, item);
         return itemData;
     }
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
index 570bf14a88f20fba76682cdc068f1626654d266e..76e6d691fcb28df0b1e715e8c7a566d3b85b9965 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/ItemData.java
@@ -19,6 +19,8 @@ import com.google.common.collect.Sets;
 import com.syncleus.aethermud.core.service.TimeTracker;
 import com.syncleus.aethermud.items.*;
 import com.syncleus.aethermud.storage.graphdb.DataUtils;
+import com.syncleus.ferma.TEdge;
+import com.syncleus.ferma.VertexFrame;
 import com.syncleus.ferma.annotations.Adjacency;
 import com.syncleus.ferma.annotations.GraphElement;
 import com.syncleus.ferma.annotations.Property;
@@ -223,7 +225,7 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
         return stats;
     }
 
-    @Adjacency(label = "Loot", direction = Direction.OUT)
+    @Adjacency(label = "loot", direction = Direction.OUT)
     public abstract <N extends LootData> Iterator<? extends N> getLootDatasIterator(Class<? extends N> type);
 
     public LootData getLootData() {
@@ -234,17 +236,17 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
             return null;
     }
 
-    @Adjacency(label = "Loot", direction = Direction.OUT)
+    @Adjacency(label = "loot", direction = Direction.OUT)
     public abstract LootData addLootData(LootData loot);
 
-    @Adjacency(label = "Loot", direction = Direction.OUT)
+    @Adjacency(label = "loot", direction = Direction.OUT)
     public abstract void removeLootData(LootData loot);
 
     public void setLootData(LootData loot) {
-        DataUtils.setAllElements(Collections.singletonList(loot), () -> this.getLootDatasIterator(LootData.class), lootData -> this.addLootData(lootData), () -> createLoottData() );
+        DataUtils.setAllElements(Collections.singletonList(loot), () -> this.getLootDatasIterator(LootData.class), lootData -> this.addLootData(lootData), () -> createLootData() );
     }
 
-    public LootData createLoottData() {
+    public LootData createLootData() {
         if( this.getLootData() != null )
             throw new IllegalStateException("Already has loot, can't create another");
         final LootData loot = this.getGraph().addFramedVertex(LootData.class);
@@ -258,14 +260,17 @@ public abstract class ItemData extends AbstractInterceptingVertexFrame {
         try {
             PropertyUtils.copyProperties(dest, src);
             if( src.getItemApplyStats() != null )
-                StatData.copyStats(dest.createItemApplyStatData(), src.getItemApplyStats());
+                StatData.copyStats((dest.getItemApplyStatData() != null ? dest.getItemApplyStatData() : dest.createItemApplyStatData()), src.getItemApplyStats());
             if(src.getLoot() != null )
-                LootData.copyLoot(dest.createLoottData(), src.getLoot());
+                LootData.copyLoot((dest.getLootData() != null ? dest.getLootData() : dest.createLootData()), src.getLoot());
             if( src.getEquipment() != null )
-                EquipmentData.copyEquipment(dest.createEquipmentData(), src.getEquipment());
-            if( src.getEffects() != null )
-                for(Effect effect : src.getEffects())
+                EquipmentData.copyEquipment((dest.getEquipmentData() != null ? dest.getEquipmentData() :dest.createEquipmentData()), src.getEquipment());
+            if( src.getEffects() != null ) {
+                for(EffectData data : dest.getEffectDatas())
+                    data.remove();
+                for (Effect effect : src.getEffects())
                     EffectData.copyEffect(dest.createEffectData(), effect);
+            }
         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
             throw new IllegalStateException("Could not copy properties", e);
         }
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java
index 3e021cfe9db687a4113af579f3b2f9bb368534ce..2a33b0936516dc81d49939f5a683dcf69f41eff1 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/LootData.java
@@ -15,10 +15,8 @@
  */
 package com.syncleus.aethermud.storage.graphdb.model;
 
-import com.syncleus.aethermud.items.Effect;
+import com.syncleus.aethermud.items.Item;
 import com.syncleus.aethermud.items.Loot;
-import com.syncleus.aethermud.stats.Stats;
-import com.syncleus.ferma.AbstractVertexFrame;
 import com.syncleus.ferma.annotations.GraphElement;
 import com.syncleus.ferma.annotations.Property;
 import com.syncleus.ferma.ext.AbstractInterceptingVertexFrame;
diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
index ba0b58c3787aa4f74de63e3274ba3776572a7930..360df09500e2e73c6edaf56b2ba8cdf783da9755 100644
--- a/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
+++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/model/NpcData.java
@@ -102,10 +102,10 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
     }
 
     @Adjacency(label = "loot", direction = Direction.OUT)
-    public abstract <N extends LootData> Iterator<? extends N> getAllLootDatas(Class<? extends N> type);
+    public abstract <N extends LootData> Iterator<? extends N> getLootDataIterator(Class<? extends N> type);
 
     public LootData getLootData() {
-        Iterator<? extends LootData> allLoots = this.getAllLootDatas(LootData.class);
+        Iterator<? extends LootData> allLoots = this.getLootDataIterator(LootData.class);
         if( allLoots.hasNext() )
             return allLoots.next();
         else
@@ -119,7 +119,7 @@ public abstract class NpcData extends AbstractInterceptingVertexFrame {
     public abstract void removeLootData(LootData loot);
 
     public void setLootData(LootData loot) {
-        DataUtils.setAllElements(Collections.singletonList(loot), () -> this.getAllLootDatas(LootData.class), lootData -> this.addLootData(lootData), () -> this.createLootData() );
+        DataUtils.setAllElements(Collections.singletonList(loot), () -> this.getLootDataIterator(LootData.class), lootData -> this.addLootData(lootData), () -> this.createLootData() );
     }
 
     public LootData createLootData() {