简体   繁体   中英

Datanucleus: embedded update object creates a new one

I'm having issues while trying to update objects with datanucleus (JDO). The problem instead of updating an existing object, it creates new ones along with new embedded data.

This is my Tracker.java:

@PersistenceCapable(detachable="true")
@FetchGroup(name="itemsList", members={@Persistent(name="items")})
@Version(strategy=VersionStrategy.VERSION_NUMBER)
public class Tracker implements java.io.Serializable {

    private static final long serialVersionUID = 2765740961462495537L;

    @Persistent
    protected String nombre;

    @Persistent(embedded="true")
    protected Item item;

    @Persistent(embeddedElement="true")
    @Element(types=Item.class, dependent="true")
    protected Collection<Item> items;

    public Tracker() {
        this.setNombre("");
        Item unItem = new Item();
        unItem.setNombre("Item principal");
        this.setItem(unItem);
        this.setItems(new HashSet<Item>());
    }

    public String getNombre() {
        return this.nombre;
    }

    public void setNombre(String unNombre) {
        this.nombre = unNombre;
    }

    public Item getItem() {
        return this.item;
    }

    public void setItem(Item unItem) {
        this.item = unItem;
    }

    public Collection<Item> getItems() {
        return this.items;
    }

    public void setItems(Collection<Item> unosItems) {
        this.items = unosItems;
    }

    public void addItem(Item unItem) {
        if (this.canAddItem(unItem)) this.getItems().add(unItem);
    }

    private Collection<String> getItemsNames() {
        Collection<String> names = new  ArrayList<String>();
        for (Item i : this.getItems()) names.add(i.getNombre());
        return names;
    }

    private boolean canAddItem(Item unItem) {
        if (this.getItemsNames().contains(unItem.getNombre())) return false;
        return true;
    }   

}

This is Item.java:

@PersistenceCapable(detachable="true",embeddedOnly="true")
@Version(strategy=VersionStrategy.VERSION_NUMBER)
public class Item implements java.io.Serializable {

    private static final long serialVersionUID = 2865740961462495537L;  

    @Persistent
    protected String nombre;

    public Item() {
        this.setNombre("");
    }
    public Item(String unNombre) {
        this.setNombre(unNombre);
    }

    public String getNombre(){
        return this.nombre;
    }

    public void setNombre(String unNombre){
        this.nombre = unNombre;
    }

}

This is the method that updates a Tracker object (only tracker's nombre attribute):

public static void guardarCambiosSobreDetachedTracker(){
        Tracker unTracker = getDetachedTracker();
        unTracker.setNombre("Nuevo nombre 2");
        printer.printTrackerFieldsStatus(unTracker);
        PersistenceManager pm = PMF.get().getPersistenceManager();
        //pm.setCopyOnAttach(false);
        Transaction tx = pm.currentTransaction();   
        try {   
            tx.begin();
            pm.getFetchPlan().addGroup("itemsList");
            pm.getFetchPlan().setFetchSize(3);

            System.out.println("ANTES DEL PERSIST: " + unTracker);
            pm.makePersistent(unTracker);
            tx.commit();

            System.out.println("DESPUES: " + unTracker);
        } finally {
            if (tx.isActive()) tx.rollback(); 
            pm.close();
        }
        printer.printTrackerFieldsStatus(unTracker);
    }

public static Tracker getDetachedTracker(){
    PersistenceManager pm = PMF.get().getPersistenceManager();  
    Transaction tx = pm.currentTransaction();
    Tracker detachedTracker = null;
    try {   
        tx.begin();
            Query q = pm.newQuery(Tracker.class);
            @SuppressWarnings("unchecked")
            List<Tracker> results = (List<Tracker>) q.execute();
            if (results.size() == 1) {
                pm.getFetchPlan().addGroup("itemsList");
                pm.getFetchPlan().setFetchSize(3);
                detachedTracker = (Tracker)pm.detachCopy(results.get(0));
                pm.detachCopyAll(results.get(0).getItems());
            } 
        //tx.commit();
    } finally {
        if (tx.isActive()) tx.rollback(); 
        pm.close();
    }

    return detachedTracker;
}

Why is it that when calling commit, instead of updating dettached embedded objects, it creates new ones besides existing embedded objects?

When you update the Tracker instance, you have to use the same PersistenceManager instance which you used to get the Tracker instance. In addition, PersistenceManager automatically detects changes made on the Tracker instance and the changes are committed to the database when appropriate, so you don't have to call makePersistent() method.

Note that makePersistent() method always inserts a new record. If what you want to do is update , you must not call makePersistent() method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM