Why do my updates not work? - java

I am new to GAE, and to JDO, I am getting stuck with how to update data.
Using the code below, if I do a getAll(), then a get() on an object, then alter an attribute for that object returned by get(), then a getAll(), the second call to getAll() returns the original un-altered object.
I tried doing a flush() but that doesn't seem to help. If I restart jetty, the data is not persisted.
public class Notes {
#SuppressWarnings("unchecked")
public List<Note> getAll() {
PersistenceManager pm = PMF.instance().getPersistenceManager();
Query query = pm.newQuery("select from com.uptecs.google1.model.Note order by subject");
return (List<Note>) query.execute();
}
public void add(Note note) {
PersistenceManager pm = PMF.instance().getPersistenceManager();
pm.makePersistent(note);
pm.flush();
}
public Note get(long id) {
PersistenceManager pm = PMF.instance().getPersistenceManager();
return (Note)pm.getObjectById(Note.class, id);
}
public void update(Note note) {
PersistenceManager pm = PMF.instance().getPersistenceManager();
pm.flush();
}
}

For a good overview look at these articles:
http://www.ibm.com/developerworks/java/library/j-gaej1/
http://www.ibm.com/developerworks/java/library/j-gaej2/index.html
http://www.ibm.com/developerworks/java/library/j-gaej3.html
2 and 3 are most relevant.
public void add(Note note) {
PersistenceManager pm = getPersistenceManagerFactory()
.getPersistenceManager();
try {
pm.makePersistent(note);
} finally {
pm.close();
}
}

Have you looked at the AppEngine Getting Started Guide? They have a pretty extensive guide on using the JDO API.
Sounds like you aren't calling close() after modifying the persistent object.

I am not very familiar with JDO but don't you have to commit() or save() your data before flush? I think only these statements will persist in the database.

Perhaps actually closing your PersistenceManagers may help (never mind the memory utilisation reasons!)

Related

JPA query not returning updated results in list

I have an issue with a webapp running in tomcat where I have an abstract DAO class with a method called all() which returns all entities from the database or JPA cache. It seems to correctly return the entities on the initial call but subsequent calls don't reflect updates happening from separate UI calls which will use the entity managers find method to find the specific entity from the list, update the relative fields and commit that. When I view that list via the same all() method later I still see the original values. If I make another update in the logs I can see the value changing from the correct value(not the original value) to the updated value and the logs shows those updates happening correctly each time.
I'm using guice for injection. I've played around with the logging and can see the same hashcode on the entity manager being used throughout a request but different for each request. I've played with the following the persistance.xml file which didn't seem to help either...
<property name="eclipselink.cache.shared.default" value="false" />
<shared-cache-mode>NONE</shared-cache-mode>
I can't see why my all() won't return updated results, I've also tried adding code to find the specific entity I'm updating in the list then replaced it by calling the following...
entity = em.find(Class.class, id)
This seemed to fix the issue on that particular entity so it appears my query is reusing old.
Here's a snippet from my DAO class
private final Provider<EntityManager> emP;
protected EntityManager em(boolean useTransaction) throws DaoException {
return useTransaction ? begin() : emP.get();
}
public List<T> all() throws DaoException {
EntityManager em = em(false);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(eClass);
Root<T> from = cq.from(eClass);
return em.createQuery(cq.select(from)).getResultList();
}
public T save(T t) throws DaoException {
return save(t, em(true));
}
protected T save(T t, EntityManager em) throws DaoException {
if (Objects.isNull(t)) {
throw new DaoException("can't save null object: " + getDaoClass(), new NullPointerException());
}
T saved;
if (t.getId() > 0) {
saved = em.merge(t);
} else {
em.persist(t);
saved = t;
}
autoCommit();
return saved;
}
protected void autoCommit() throws DaoException {
if (autoCommit) {
commit();
}
}
public void commit() throws DaoException {
EntityManager em = emP.get();
if (!em.getTransaction().isActive()) {
throw new DaoException("transaction isn't active, unable to commit");
}
try {
em.getTransaction().commit();
} catch (IllegalStateException e) {
throw new DaoException("transaction not active", e);
} catch (RollbackException e) {
throw new DaoException("commit rolled back", e);
}
}
So I'm wondering if anyone has any insights on why this might be happening or have any suggestions on what else I can try to check?
So I found the cause of the issue I was having. I was using the ElementCollection annotation in my entities when referencing lists. I removed the annotation and replaced it with a JoinTable and OneToMany annotations and things are working correctly.
The issue I had was that the entity would be stored in the database fine and I was updating that entity as expected but JPA had embedded the list of entities where it was referenced.
So I was seeing the embedded list returned each time which was not the actual entity I had updated. My entities are now using proper join tables instead of embedded objects and everything is behaving as expected.

What Dropwizard-Hibernate doc is trying to say?

I have run into LazyInitializationException and then I ran into the following paragraph from the official doc. Unfortunately, it makes absolutely no sense to me. Please help.
(The code block above the paragraph in the doc.)
#GET
#Timed
#UnitOfWork
public Person findPerson(#PathParam("id") LongParam id) {
return dao.findById(id.get());
}
Important
The Hibernate session is closed before your resource method’s return
value (e.g., the Person from the database), which means your resource
method (or DAO) is responsible for initializing all lazily-loaded
collections, etc., before returning. Otherwise, you’ll get a
LazyInitializationException thrown in your template (or null values
produced by Jackson).
First The Hibernate session is closed before your resource method’s return value. How is this possible? This would have been possible had there been a try-finally block around my resource's return statement, but that is not the case here.
My resource should have been invoked by another method, which I am guessing would open the Hibernate session before my resource method is invoked and would then close the session after my resource method returns. How can it close it before my method returns. I don't get it.
The most important part - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. I have no Hibernate experience. I am using it for the first time now. How do I initialize, or rather what is exactly is meant by "initialize" in context of Hibernate? A code example will help a lot.
PS: This question might look odd, and someone at a cursory glance might even suggest to move it to "English Language and Usage", but please read it carefully. This is a technical question, not paragraph dissection.
Edit:
Added the code block from the doc else it won't make sense anyone. Also I removed one paragraph from my question, which became clear to me, immediately after posting the question.
First The Hibernate session is closed before your resource method’s
return value. How is this possible? This would have been possible had
there been a try-finally block around my resource's return statement,
but that is not the case here.
I know nothing about Dropwizard. So let's see the source (I change it a bit).
From UnitOfWorkAwareProxyFactory
class UnitOfWorkAwareProxyFactory {
public <T> T create(Class<T> clazz) {
final ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(clazz);
final Proxy proxy = (Proxy) factory.createClass().newInstance();
proxy.setHandler(new MethodHandler() {
#Override
public Object invoke(Object self, Method overridden,
Method proceed, Object[] args) {
final UnitOfWork unitOfWork = overridden.getAnnotation(UnitOfWork.class);
final UnitOfWorkAspect unitOfWorkAspect = new UnitOfWorkAspect(sessionFactories);
try {
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = proceed.invoke(self, args);
unitOfWorkAspect.afterEnd();
return result;
} catch (Exception e) {
unitOfWorkAspect.onError();
throw e;
}
}
});
return (T) proxy;
}
}
if you have a class
class PersonDao {
#UnitOfWork
public Person findPerson(LongParam id) {
return dao.findById(id.get());
}
}
You can do something like this
UnitOfWorkAwareProxyFactory factory = new UnitOfWorkAwareProxyFactory();
PersonDao proxy = factory.create(PersonDao.class);
when you do
Person person = proxy.findPerson(1L);
that line becomes
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = findPerson.invoke(proxy, 1L);
unitOfWorkAspect.afterEnd();
return result;
Methods unitOfWorkAspect.beforeStart(unitOfWork) and unitOfWorkAspect.afterEnd() from the source UnitOfWorkAspect
class UnitOfWorkAspect {
public void beforeStart(UnitOfWork unitOfWork) {
session = sessionFactory.openSession();
configureSession();
beginTransaction();
}
public void afterEnd() {
try {
commitTransaction();
} catch (Exception e) {
rollbackTransaction();
throw e;
} finally {
session.close();
}
}
}
The most important part - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. I have no Hibernate experience. I am using it for the first time now. How do I initialize, or rather what is exactly is meant by "initialize" in context of Hibernate?
Initialize in this context means the collection data should be loaded from a database. Some methods of an initialization
1.Use an eager loading, for an example
class User {
#ManyToMany(fetch = FetchType.EAGER)
private List<Role> roles;
}
Hibernate will load roles via joins or subselects, when you get a User entity.
Use Hibernate.initialize(user.getRoles())
Use join fetch in HQL — from User user left join fetch user.roles
Use Criteria with setFetchMode()
Use fetch profiles, entity graphs. Don't know can entity graphs be used with a session, it is a JPA feature: http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/fetching/Fetching.html
If you don't need to fetch collections, you can use a partial objects loading with transforming to the root entity: How to transform a flat result set using Hibernate

Why does JDO think this detached object is clean?

I am trying to learn JDO (and at the same time its GAE and Spring intricacies) by creating a small web app, and am having trouble getting updated domain objects to persist back to the database. I initially grab the entity from the DB and detach it so that I can show it to the user and allow them to change it. Once the user has made the changes and posts the form back to the app, I again grab the entity from the DB (detached), update its properties, and then call a pm.makePersistent(). The abbreviated code is as follows:
User Domain Object:
#PersistenceCapable(detachable="true")
public class User extends BaseEntity {
#Persistent
private String firstName = "";
#Persistent
private String middleInitial = "";
#Persistent
private String lastName = "";
}
DAO Read Method:
public User read(Key key) throws DataException {
PersistenceManager pm = PMF.get().getPersistenceManager();
User pkg, detached = null;
try {
pkg = (User) pm.getObjectById(User.class, key);
detached = pm.detachCopy(pkg);
detached.setIsAlreadyInDB(true);
}
catch (Exception e) {
throw new DataException("An error occured trying to read the User object. Details:\n" + e.getMessage());
}
finally {
pm.close();
}
return detached;
}
DAO Update Method:
private void update(User pkg) throws DataException {
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(pkg);
tx.commit();
}
finally {
if (tx.isActive()) tx.rollback();
pm.close();
}
}
Now when I get down into the update method, I've proven to myself that I'm working with just the same object from my read via inspecting its hashCode(), I've changed a value using the domain object's setter method, I've even printed the changed value to the console to make sure it's getting done, and JDOHelper.isDirty() still returns false, and therefore none of the changes get persisted back to the database.
Any thoughts on what I'm missing or if I'm approaching this from the wrong angle? Thank you for helping out a JDO beginner!
JDOHelper.isDirty is for managed objects. A detached object is not managed. DataNucleus provides a helper method of its own to get the dirty fields while detached since the logic is implementation-specific
String[] dirtyFieldNames = NucleusJDOHelper.getDetachedObjectDirtyFields(obj, pm);

JDO not fetching collection member field

Have a class:
class Node implements Serializable
{
private String name;
public String getName { return name; }
public void setName(String val){ name = val; }
public Node(){}
}
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
class NodeBag implements Serializable
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;
#Persistent(serialized="true")
private ArrayList<Node> nodes = new ArrayList<Node>();
public String getNodes { return nodes; }
public void setNodes(ArrayList<Node> val){ nodes = val; }
public NodeBag(){}
}
I can save it to the db with this
PersistenceManager pm = PMF.getManager();
try
{
pm.makePersistent(newBag);
}
finally
{
pm.close();
}
But when i load it back
PersistenceManager pm = PMF.getManager();
Query q = pm.newQuery(NodeBag.class);
try
{
List<NodeBag> pipelines = (List<NodeBag>)q.execute();
return nodeBags; // nodeBags[0].nodes is always empty
}
finally
{
q.closeAll();
}
Nodebag.nodes is always empty!
Did i miss something?
Thanks in advance.
Regards,
Paul
In your call to return the objects you can use the FetchPlan to specify what FetchGroup to return. See JDO docs for more information on the FetchGroup options.
You can ensure that all the entities are fetched, by specifying in your PersistenceManager the FetchGroup to use. The modified code is shown below:
PersistenceManager pm = PMF.getManager();
pm.getFetchPlan().setGroup(FetchGroup.ALL);
Query q = pm.newQuery(NodeBag.class);
try {
List<NodeBag> pipelines = (List<NodeBag>)q.execute();
return nodeBags; // nodeBags[0].nodes is always empty
} finally {
q.closeAll();
}
I had a heck of a time getting fetch groups to work. Both Query and PersistenceManager have a getFetchPlan(), but only the one on PersistenceManager seems to work.
Also, make sure you make your objects detachable and use pm.detachCopyAll() on the result.
Missed putting it in the fetch plan ? mark in default fetch group perhaps, or access the field, or put in a custom fetch plan, as per the DataNucleus docs and JDO spec.
Actually, i wanted also the return the answer across the wire by converting it to JSON.
And i've managed to load the child objects. The trick i use is detach. By detaching, everything will be loaded.
Thanks.
Use Collection insted of List and it should start working as long as it is inside a transaction

JDO - Updating an Object

i am experimenting with the Google App Engine, and the persist option JDO.
I would like to know if it is possible to map a transient object to a persist object? Or something to update the persistent object with the use of an transient object?
I the coding examples i see the following piece of code to update objects:
public void updateEmployeeTitle(User user, String newTitle) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Employee e = pm.getObjectById(Employee.class, user.getEmail());
if (titleChangeIsAuthorized(e, newTitle) {
e.setTitle(newTitle);
} else {
throw new UnauthorizedTitleChangeException(e, newTitle);
}
} finally {
pm.close();
}
}
But this is not what i want, does anybody know if i can update the whole object like JPA does: object.update();
So i would like something like this:
public User update(User u) {
PersistenceManager pm = PMF.get().getPersistenceManager();
User usr;
try {
usr = pm.getObjectById(User.class, u.getId());
// copy transient object u to persist object usr.
// on update of usr all changes in object u are persistent.
} finally {
pm.close();
}
return u;
}
A "transient" object has no "identity" so there is no way to locate it in a datastore. Think carefully if you want to use transient objects, or whether it would be better to just use detached objects. JPA uses the equivalent of a "detached" object. JDO can do that too and then you just call pm.makePersistent(detachedObj);
--Andy (DataNucleus)

Categories