尝试使用datanucleus(JDO)更新对象时遇到问题。这个问题不是更新现有对象,而是创建新的对象以及新的嵌入数据。
这是我的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;
}
}
这是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;
}
}
这是更新Tracker对象的方法(仅限跟踪器的nombre属性):
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;
}
为什么调用commit时,除了更新dettached嵌入对象外,还会创建除现有嵌入对象之外的新对象?
答案 0 :(得分:1)
更新Tracker
实例时,您必须使用用于获取PersistenceManager
实例的相同 Tracker
实例。此外,PersistenceManager
会自动检测对Tracker
实例所做的更改,并在适当时将更改提交到数据库,因此您不必调用makePersistent()
方法。
请注意, makePersistent()
方法始终会插入新记录。如果您想要做的是更新,则不得调用makePersistent()
方法。