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.