У меня есть проблема, которую я не могу решить.Я пытался искать в Интернете решения, но я не нашел ни одного общего решения.Я хочу обновить объект, каким бы он ни был, в хранилище данных.Для этого вот код, который я использую для проекта
Я использую DataNucleus и Google AppEngine.
Вот мой jdoconfig.xml
<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">
<persistence-manager-factory name="transactions-optional">
<property name="javax.jdo.PersistenceManagerFactoryClass"
value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
<property name="javax.jdo.option.ConnectionURL" value="appengine"/>
<property name="javax.jdo.option.NontransactionalRead" value="true"/>
<property name="javax.jdo.option.NontransactionalWrite" value="true"/>
<property name="javax.jdo.option.RetainValues" value="true"/>
<property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
</persistence-manager-factory>
</jdoconfig>
Мой PMFclass
public final class PMF {
private static final PersistenceManagerFactory pmfInstance =
JDOHelper.getPersistenceManagerFactory("transactions-optional");
private PMF() {}
public static PersistenceManagerFactory get() {
return pmfInstance;
}
public static PersistenceManager getPersistenceManager() {
return pmfInstance.getPersistenceManager();
}
}
Мой класс BaseModel, который является суперклассом для всех моделей проекта
@Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
public abstract class BaseModel implements Serializable {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
protected Key id;
public boolean equals(Object obj) {
try {
return obj instanceof BaseModel ? this.getId().getId() == ((BaseModel) obj).getId().getId() : false;
} catch (Exception e) {
return false;
}
}
}
Вот класс (Project
), который я хочу сохранить
@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
public class Project extends BaseModel implements BeanModelTag {
private static final long serialVersionUID = 3318013676594981107L;
@Persistent
private String name;
@Persistent
private String description;
@Persistent
private Date deadline;
@Persistent
private Integer status;
@Persistent
private Key manager;
@Persistent
private Set<Key> team;
}
Для этого я попробовал несколько вещей.Этот метод ниже сохраняет новый экземпляр Project с успехом, но когда я призываю обновить уже отсоединенный объект, обновляется только поле deadline , остальные атрибуты не обновляются (и все же я пошелв режиме отладки, чтобы проверить, изменились ли другие атрибуты, и да, они были, но сохранен только крайний срок get).
public void save(BaseModel object) {
PersistenceManager pm = PMF.getPersistenceManager();
try {
pm.makePersistent(object);
} finally {
pm.close();
}
}
Итак, я попробовал следующий код
public void update(Project object) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.currentTransaction().begin();
Project p = pm.getObjectById(Project.class, object.getId());
p.setName(object.getName());
p.setDeadline(object.getDeadline());
p.setDescription(object.getDescription());
p.setTeam(p.getTeam());
p.setStatus(object.getStatus());
pm.currentTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
pm.currentTransaction().rollback();
} finally {
pm.close();
}
}
И это сработало.Хорошо, это работает таким образом, но мне нужен универсальный метод для всех моих моделей, поэтому я попробовал это
public void update(BaseModel object) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.currentTransaction().begin();
BaseModel ob = pm.getObjectById(object.getClass(), object.getId());
for (Field f : ob.getClass().getDeclaredFields()) {
if (!f.toString().contains("final")) {
f.setAccessible(true);
for (Field g : object.getClass().getDeclaredFields()) {
g.setAccessible(true);
if (f.getName().equals(g.getName())) {
f.set(ob, g.get(object));
}
g.setAccessible(false);
}
}
f.setAccessible(false);
}
pm.makePersistent(ob);
pm.currentTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
pm.currentTransaction().rollback();
} finally {
pm.close();
}
}
Но это не работает вообще, ничего не сохраняется, и все же, когда я System. Атрибуты вручную, они изменены.Я пытался с и без pm.makePersistent(ob);
без удачи.Я не знаю что делатьУ меня есть 120 моделей в этом проекте, которые наследуются от BaseModel
, и я не могу найти способ сделать обновление, которое работает с моей моделью.
----------- Редактировать -----------
Спасибо за ответ.Вот мое решение на данный момент.Конечно, это printStrackTree оттуда выйдет.
public void update(BaseModel object) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.currentTransaction().begin();
BaseModel ob = pm.getObjectById(object.getClass(), object.getId());
for (Field f : ob.getClass().getDeclaredFields()) {
if (!Pattern.compile("\\bfinal\\b").matcher(f.toString()).find()) {
f.setAccessible(true);
for (Field g : object.getClass().getDeclaredFields()) {
g.setAccessible(true);
if (f.getName().equals(g.getName())) {
f.set(ob, g.get(object));
JDOHelper.makeDirty(ob, f.getName());
}
g.setAccessible(false);
}
f.setAccessible(false);
}
}
pm.makePersistent(object);
pm.currentTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
pm.currentTransaction().rollback();
} finally {
pm.close();
}
}