I'm new to hibernate and i have this problem.
If i do this:
Session sesion = HibernateUtil.getSessionFactory().openSession();
Transaction tx = sesion.beginTransaction();
A obj = (A) session.load(A.class,id);
System.out.println(obj);
tx.commit();
session.close();
return obj;
There is no problem and the gui shows the object's data.
But if i do this:
Session sesion = HibernateUtil.getSessionFactory().openSession();
Transaction tx = sesion.beginTransaction();
A obj = (A) session.load(A.class,id);
// i don't use System.out.println(obj);
tx.commit();
session.close();
return obj;
The gui doesn't show anything and i got the following exception.
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I've been reading the api but it's a whole new world to me.
Does anyone knows what's going on?
Instead of using session.load(..), you need to use session.get(..)
A obj = (A) session.get(A.class,id);
The session.load(..) lazy loads the object using a proxy, hence if the object is not accessed (in your example using System.out.println) the object stays uninitialised. When an uninitialised object is accessed outside the hibernate session (called a detached object), a LazyInitializationException is generated - as the proxy object has no way of retrieving the properties of the object from a hibernate session.
The session.get(..) doesn't lazy load the object, so it is still accessible outside the session. There are few other nuances of get vs load, thus, I highly recommend you visit the following post about their difference:
Understanding Get vs Load: http://razshahriar.com/2009/01/hibernate-load-vs-get-differences/
load method use lazy loading to load its dependent(child) objects. If you do not read the object within session, it will throw LazyInitializationException.
Use Hibernate.initialize(object) to initialize all the child objects so that you can use it without session.
Related
I would like to have access to a Hibernate mapped object inside the transaction that creates it in order to make a clone of it. There is a reason I want to make a clone of it via the Hibernate Session and not just using Object.clone() (long story...).
Transaction tran = session.beginTransaction();
Gadget gadg = new Gadget(1 /* id */, "Gadget Name", "some label", 123);
session.save(gadg);
//this returns null
Gadget gadgClone = (Gadget)session.get(Gadget.class, gadg.getId());
//do something with the clone
tran.commit();
However, gadgClone is null. Is it because it has not been committed yet? Is there a way to make it accessible in the session before committing?
Why don't you clone the object before persisting it?
Why do you clone it after un-persisting it?...
Anyhow, have you tried to load the object from the cache? For performance reasons, you don't need to hit the database if your object resides in the cache.
Gadget savedGadg = (Gadget) session.load(Gadget.class, gadg.getId());
Further you may need to initialize the object (and perhaps its fields), all before committing the transaction.
Hibernate.initialize(savedGadg);
Hibernate.initialize(savedGadg.getCertainCollection());
In my Java program I want to marshal my Hibernate persistent objects to XML.
For this i am using JAXB. The problem is when marshalling the object i got a NullPointerException.
This is caused by the lazy load fetching strategy. When switching to eager fetching the marshaling process works.
I use the getter instead of the variable so Hibernate can initialize the object. I got no LazyInitializationException so there is no closed session etc.
Pseudocode:
Session s = sessionFactory.openSession();
Criteria crit = s.createCriteria(Entity.class);
List list = crit.list();
Entity entity = (Entity) list.get(0)
try {
DocumentResult dr = new DocumentResult();
context = JAXBContext.newInstance(entity.getclass());
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(entity, dr);
}
catch(JAXBException e) {
// ignore
}
If you are marshalling lazy loaded attributes of your entity then it cannot be detached, aka it needs to be associated with an active session. Your options are:
Retain the session the original entity was loaded in, long enough to
complete the marshalling.
Start a new sessions and merge your entity into it, then perform
the marshalling.
Make your lazy loaded attributes eager.
On a side note I find it odd that you are getting a null pointer exception. You must be swallowing a LazyInitializationException somewhere in your code.
I am facing a lazy load exception which I cannot figure out.
First I fetch with a usual find method from the entity manager an entity. After that I run method which part of it is :
object = getUnproxiedValue(object);
if (object == null) {
... // this part is not run
return;
}
if (object instanceof Collection ) {
... // and I fall here with lazy load exception
return;
}
The getUnproxiedValue suppose to give object when the argument object is a proxy, the proxy is initialized (loaded) and the un-wrapped object is returned. Something goes wrong beacuse when there is a collection sometimes it dies with an lazy load exception, beacuse object is null so why the first condition did not work ?
For any clues and hints thank you in advance, and I really greatly appreciate any support in this.
Regards,
P.
LazyLoadingException identifes that you're trying to get data from db without a transaction. Try use #TransactionAttribute annotation to ensure you run your if (object instanceof Collection ) { block in transaction.
Are you using EJB Beans? Your entity Object is detached, when you leave the transaction. So you cannot load any dependent Entities (lazy Loading). You could use an extended persistence context entity manager together with a stateful session bean. Then you can use lazy loading outside a transaction. And your Entity is keep in sync with the database.
I learnt Hibernate and used it to reduce my Java code to a vast extent and also able
to reduce the time spent for DB's. Now what type of query should i use to finish my
operations for getting a DB list to be displayed, to update and delete.
My code for deletion is
String newToken = "DELETEUSER";
if(!TokenManager.checkRoleToken(newToken)){
return;
}
Session session = Main.getSession(); //calling the main method to get sesion
Leavetable table = new Leavetable; // intialisation of object table
try{
Transaction tr = session.beginTransaction();
table = session.createQuery();
session.delete(table); // deletion of the object and its properties from selected leaveID
tr.commit();
}
finally{
session.close();
}
My code for Db updation
public void updateLeaveTable( Leavetable leave ) {
String newToken = "ADDUSER";
if( !TokenManager.checkRoleToken( newToken ) ) {
return;
}
Session session = Main.getSession(); // calling the main method to get
// session
try {
session = Main.getSession();
Transaction tr = session.beginTransaction();
session.saveOrUpdate( leave ); // here without query the table gets
// updated How?
tr.commit();
}
finally {
session.close();
}
}
What type of query should I follow. My final task before going into project. When I
know this will start my life as a developer. Any suggestions Please.
Do you mean a HQL query? Well, a typical query on your Leavetable entity would looks like this:
Query q = session.createQuery("from Leavetable t where t.someField = :value");
q.setParameter("value", foo);
List<Leavetable> results = q.list();
However, if you just want to retrieve an entity by identifier, see Session#load() or Session#get(). I don't want to make things too much confusing but while both methods are similar, there is an important difference between both of them. Quoting the Hibernate Forums:
Retrieving objects by identifier
The following Hibernate code snippet
retrieves a User object from the
database:
User user = (User) session.get(User.class, userID);
The get() method is special because
the identifier uniquely identifies a
single instance of a class. Hence it’s
common for applications to use the
identifier as a convenient handle to a
persistent object. Retrieval by
identifier can use the cache when
retrieving an object, avoiding a
database hit if the object is already
cached. Hibernate also provides a
load() method:
User user = (User) session.load(User.class, userID);
The load() method is older; get() was
added to Hibernate’s API due to user
request. The difference is trivial:
If load() can’t find the object in
the cache or database, an exception is
thrown. The load() method never
returns null. The get() method
returns null if the object can’t be
found.
The load() method may return a proxy
instead of a real persistent instance.
A proxy is a placeholder that triggers
the loading of the real object when
it’s accessed for the first time; we
discuss proxies later in this section.
On the other hand, get() never
returns a proxy.
Choosing between get() and load()
is easy: If you’re certain the
persistent object exists, and
nonexistence would be considered
exceptional, load() is a good
option. If you aren’t certain there is
a persistent instance with the given
identifier, use get() and test the
return value to see if it’s null.
Using load() has a further
implication: The application may
retrieve a valid reference (a proxy)
to a persistent instance without
hitting the database to retrieve its
persistent state. So load() might
not throw an exception when it doesn’t
find the persistent object in the
cache or database; the exception would
be thrown later, when the proxy is
accessed.
Of course, retrieving an object by
identifier isn’t as flexible as using
arbitrary queries.
See also the Hibernate Documentation (links below).
Reference
Hibernate Core Reference Guide
10.3. Loading an object
Chapter 14. HQL: The Hibernate Query Language
The Hibernate JavaDoc states that Session.update(Object o) would raise an exception if there's already a persistent instance of o, right?
If there is a persistent instance with the same identifier, an exception is thrown.
However, the following code doesn't throw anything when I run it. And I think it should!
Email email = new Email("andre", "girafa", "hi");
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
session.save(email);
session.update(email);
session.update(email);
tx.commit();
// didn't throw... Let's try again
tx = session.beginTransaction();
session.update(email);
session.update(email);
tx.commit();
session.close();
// still nothing! :(
As you can say, twice I try to do multiple update()s, but still Hibernate's taking easy on me.
Anybody has a hunch why?
EDIT: it seems that it would only throw if another equivalent object, for instance, email2 with the same ID as email. I guess the documentation was kinda sloppy there.
Update in Hibernate is not UPDATE in SQL language. Hibernate handles SQL UPDATEs
automatically through state cache in Session object.
But it's only for entities loaded in current session. This method, session.update(object) is meant for attaching object from another tier to current session to track and, possible, update at the end.
In your case it's just an NOOP. It'll sourly throw if:
Email email = new Email("andre", "girafa", "hi");
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
int id = session.save(email);
Email anotherEmail = new Email("", "", "");
anotherEmail.id = id;
session.update(anotherEmail); // will throw
You could read more about update method semantics on Hibernate reference.
No error because it's the same instance you're updating.
The error is thrown if a DIFFERENT persistent instance is present in the session and you try to update().
Can you try with a session.flush()? To see if that raises the exception (sometimes commit may not flush data depending on flush mode).
Although I would say the exception is only thrown if the object was updated outside the scope of the current session, let's say by a concurrent client.
I suggest you always stick to EntityManager.merge instead of Hibernate update method, update is quite confusing.
I found this article explain very clear which I always refer to.
As with persist and save, the update method is an “original” Hibernate
method that was present long before the merge method was added. Its
semantics differs in several key points:
it acts upon passed object (its return type is void); the update method transitions the passed object from detached to persistent
state;
this method throws an exception if you pass it a transient entity.
In the following example we save the object, then evict (detach) it
from the context, then change its name and call update. Notice that we
don’t put the result of the update operation in a separate variable,
because the update takes place on the person object itself. Basically
we’re reattaching the existing entity instance to the persistence
context — something the JPA specification does not allow us to do.
Person person = new Person();
person.setName("John");
session.save(person);
session.evict(person);
person.setName("Mary");
session.update(person);
Trying to call update on a transient instance will result in an
exception. The following will not work:
Person person = new Person();
person.setName("John");
session.update(person); // PersistenceException!
In order to understand the part above, you need to understand the difference betweentransient and detached object.