what is meaning of could not initialize proxy - no Session error?? what meaning of lazy object and why occur??, and how to avoid it without change the hibernate laze property and without using Hibernate.initialize() because that doesn't work for me.
There are a couple of things here, first of all you appear to asking "what is lazy loading".
If you have an object to be loaded from the database which has a relationship with another object, lazy loading allows you to only load the required object, and the related object will only be loaded when you need it.
The exception you are having is caused by trying to access the related object after the objects have been disconnected from the database session (obviously a db session is required to load them).
There are a few ways we can deal with the situation, the most appropriate will entirely depend your application.
You can always load all the data you need inside the transaction where the object is first loaded (Hibernate.initialise, or sometimes just calling the getter will work), this will remove your exception: the down side to this is to will find that you are regularly leading a lot of data and could have performance issues
Another way is to pass the Id to where you need to use the object, load a new one from the database and do your work inside the transaction, passing ids a lot is not very OO but sometimes it's the best option.
If for instance you are having this error in UI bindings or other places where you only want to "get", you may want to consider a "session in view" which will provide a db session for your lazy loading.
I can not tell you what is the best option without knowing about your application and it's architecture.
If you wish to discuss a any of this further please let me know.
You should mark your method with annotation #Transactional
#Transactional
void method(){
Entity e = ... (from database);
e.getLazyField();
}
Related
Well, i have class named "Consultation" that have a list of "ItemBudget", and i have a class named "Budget" that have a list of "ItemOrcamento" too. The relation Consultation<-->ItemBudget is ManyToMany, and relation Budget<-->ItemBudget is OneToMany.
In JSF i do the following:
<p:dataTable rowKey="#{item.id}" var="item" value="#{consultationMB.consultation.budget.itensAsList}" selection="#{consultationMB.itemBudget}" >
I use method "getItensAsList" that return a ArrayList() instead of a HashSet() that primefaces dataTable tag can't read correctly
As you can see, my selection is "itemBudget", so in my ManagedBean called ConsultationMBImpl i try to execute the following:
if (!itemBudget.getSituation().getCode().equals("WAITING_CONCLUSION")){
//some code here
}
When i try make the code above all fields that have reference to another class like: Situation, Dentist and others have this: "Dentist_javassist_32", "Situation_javassist_49"...
And all fields are null or zero.
That's caused by Hibernate, which loads a proxy (suffixed with _javassist) instead of the original object. If you debug your code with an IDE and try to call a getter on the fly, you'll get the real value, even it seems to be null for the property.
Why is it that done? Because it's much faster to load proxies rather than real objects for the ORM tool. Hibernate keeps a cache with already loaded objects instead of hitting the DB once and again.
If you want to avoid lazy loading, you could use a get instead of a load method over Hibernate's Session. Also for its relations, you can mark them as lazy="false", so Hibernate will load them as real objects. If you want to directly unproxy an already loaded instance, there are also some methods to achieve that.
However, don't do that unless you strictly require it. As I said before, that will make Hibernate load more information from DB and consequently, loose eficiency.
I was wondering if there was a way to tell Hibernate to generate some kind of console warning when it has too many objects of a certain type in the session cache. I would like to do this for load testing as we have OutOfMemoryException problems on occasion with BLOB loading from Oracle.
We are still using Hibernate 3.6.10 for now. Our best approach for this testing at the moment is to just generate more data than the system would be able to handle in a normal use case and try to load the parent object and see if it crashes. Doing it this way just feels kind of bad.
Any suggestions are welcome.
One note that I forgot to mention is that this "logging" idea is something I would like to be able to leave in production code to pinpoint specific problems.
- EDIT -
Here's an example of what I'm trying to do:
Say I have an #Entity ClassX that has a lazy loaded list of #Entity ClassY objects. Some how, I would like to have a log message spit out when 100 or more instances of ClassY are loaded into the session cache. This way, during development I can load a ClassX object and notice if I (or another developer on the team) happen to be accessing that list when I shouldn't be.
You could attach an Interceptor to listen to object load events, maintaining a count for each unique entity type and logging a warning whenever it goes past a certain threshold. The documentation shows you how to define a session-scoped interceptor, by passing it in at creation time:
Session session = sf.openSession( new AuditInterceptor() );
Most likely you're not creating your Session manually so this may not be helpful, but possibly the way that you are declaring your session has some way of passing an Interceptor through.
It's easier to declare a SessionFactory-scoped Interceptor but it doesn't seem to give you any reference back to the Session that the object is being created within, otherwise you'd be able to knock up some sort of counter in a WeakHashMap (with Session as the key so that you don't leak memory). If you're using the default Thread-local session strategy then you could always ask sessionFactory.getCurrentSession().
I am learning hibernate and i am using the debugger to understand how hibernate fetches objects. I have enabled lazy loading in my XML and i use create a query to get an object. This object has a Set associated with it.
When i look at the variable values in my debugger it seems to be completely loading the object graph, ie not lazily fetching the set and its properties. I can think of several reasons why this might be the case.
1) something is wrong with my xml / config and i have eager fetching enabled. I'm not sure this is the case, everything is at its defaults which is to lazy fetch.
2) The way the IDE debugger works is that is causes hibernate to trigger the lazy loading when i look at them.
3) Hibernate is fetching the entire object graph from the 2nd level cache. Ive tried to disable this but this seems to have no effect
Any other ideas?
Debugging (showing the lazy fields, to be precise) triggers the lazy loading already. Get the entity, detach it and access your lazy field. Should throw some sort of exception if lazy loading works.
If you really want to know how hibernate does it, have a look at the sources.
#atamanroman's answer is fully correct. I just wanted to add in some details. In order to test lazy loading in a JavaEE environment, I use Arquillian tests. In the test class, use a UserTransaction to control transaction boundaries. After committing the transaction, access the lazy loaded attribute and expect an Exception
#Inject
private UserTransaction tx;
#Test(expected=Exception.class)
public void testLazyLoading() throws Exception {
tx.begin();
MyEntity entity = em.find(entityId);
tx.commit();
entity.getLazyLoadedProperty().someMethod();
}
Please note that in order to trigger the loading of a lazy loaded attribute, it is often not enough to call the getter inside the transaction, you must also perform some operation with the attribute, like calling size() on a list. Otherwise, the getter will simply return a proxy.
I'm building an application using JPA 2.0 (Hibernate implementation), Spring, and Wicket. Everything works, but I'm concerned that my form behaviour is based around side effects.
As a first step, I'm using the OpenEntityManagerInViewFilter. My domain objects are fetched by a LoadableDetachableModel which performs entityManager.find() in its load method. In my forms, I wrap a CompoundPropertyModel around this model to bind the data fields.
My concern is the form submit actions. Currently my form submits pass the result of form.getModelObject() into a service method annotated with #Transactional. Because the entity inside the model is still attached to the entity manager, the #Transactional annotation is sufficient to commit the changes.
This is fine, until I have multiple forms that operate on the same entity, each of which changes a subset of the fields. And yes, they may be accessed simultaneously. I've thought of a few options, but I'd like to know any ideas I've missed and recommendations on managing this for long-term maintainability:
Fragment my entity into sub-components corresponding to the edit forms, and create a master entity linking these together into a #OneToOne relationship. Causes an ugly table design, and makes it hard to change forms later.
Detach the entity immediately it's loaded by the LoadableDetachableModel, and manually merge the correct fields in the service layer. Hard to manage lazy loading, may need specialised versions of the model for each form to ensure correct sub-entities are loaded.
Clone the entity into a local copy when creating the model for the form, then manually merge the correct fields in the service layer. Requires implementation of a lot of copy constructors / clone methods.
Use Hibernate's dynamicUpdate option to only update changed fields of the entity. Causes non-standard JPA behaviour throughout the application. Not visible in the affected code, and causes a strong tie to Hibernate implementation.
EDIT
The obvious solution is to lock the entity (i.e. row) when you load it for form binding. This would ensure that the lock-owning request reads/binds/writes cleanly, with no concurrent writes taking place in the background. It's not ideal, so you'd need to weigh up the potential performance issues (level of concurrent writes).
Beyond that, assuming you're happy with "last write wins" on your property sub-groups, then Hibernate's 'dynamicUpdate' would seem like the most sensible solution, unless your thinking of switching ORMs anytime soon. I find it strange that JPA seemingly doesn't offer anything that allows you to only update the dirty fields, and find it likely that it will in the future.
Additional (my original answer)
Orthogonal to this is how to ensure you have a transaction open when when your Model loads an entity for form binding. The concern being that the entities properties are updated at that point and outside of transaction this leaves a JPA entity in an uncertain state.
The obvious answer, as Adrian says in his comment, is to use a traditional transaction-per-request filter. This guarantees that all operations within the request occur in single transaction. It will, however, definitely use a DB connection on every request.
There's a more elegant solution, with code, here. The technique is to lazily instantiate the entitymanager and begin the transaction only when required (i.e. when the first EntityModel.getObject() call happens). If there is a transaction open at the end of the request cycle, it is committed. The benefit of this is that there are never any wasted DB connections.
The implementation given uses the wicket RequestCycle object (note this is slightly different in v1.5 onwards), but the whole implementation is in fact fairly general, so and you could use it (for example) outwith wicket via a servlet Filter.
After some experiments I've come up with an answer. Thanks to #artbristol, who pointed me in the right direction.
I have set a rule in my architecture: DAO save methods must only be called to save detached entities. If the entity is attached, the DAO throws an IllegalStateException. This helped track down any code that was modifying entities outside a transaction.
Next, I modified my LoadableDetachableModel to have two variants. The classic variant, for use in read-only data views, returns the entity from JPA, which will support lazy loading. The second variant, for use in form binding, uses Dozer to create a local copy.
I have extended my base DAO to have two save variants. One saves the entire object using merge, and the other uses Apache Beanutils to copy a list of properties.
This at least avoids repetitive code. The downsides are the requirement to configure Dozer so that it doesn't pull in the entire database by following lazy loaded references, and having yet more code that refers to properties by name, throwing away type safety.
I am getting this exception in a controller of a web application based on spring framework using hibernate. I have tried many ways to counter this but could not resolve it.
In the controller's method, handleRequestInternal, there are calls made to the database mainly for 'read', unless its a submit action.
I have been using, Spring's Session but moved to getHibernateTemplate() and the problem still remains.
basically, this the second call to the database throws this exception. That is:
1) getEquipmentsByNumber(number) { firstly an equipment is fetched from the DB based on the 'number', which has a list of properties and each property has a list of values. I loop through those values (primitive objects Strings) to read in to variables)
2) getMaterialById(id) {fetches materials based on id}
I do understand that the second call, most probably, is making the session to "flush", but I am only 'reading' objects, then why does the second call throws the stale object state exception on the Equipment property if there is nothing changed?
I cannot clear the cache after the call since it causes LazyExceptions on objects that I pass to the view.
I have read this:
https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0
but could not solve the problem based on the suggestions provided.
How can I solve this issue? Any ideas and thoughts are appreciated.
UPDATE:
What I just tested is that in the function getEquipmentsByNumber() after reading the variables from list of properties, I do this: getHibernateTemplate().flush(); and now the exception is on this line rather then the call to fetch material (that is getMaterialById(id)).
UPDATE:
Before explicitly calling flush, I am removing the object from session cache so that no stale object remains in the cache.
getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();
OK, so now the problem has moved to the next fetch from DB after I did this. I suppose I have to label the methods as synchronized and evict the Objects as soon as I am finished reading their contents! it doesn't sound very good.
UPDATE:
Made the handleRequestInternal method "synchronized". The error disappeared. Ofcourse, not the best solution, but what to do!
Tried in handleRequestInternal to close the current session and open a new one. But it would cause other parts of the app not to work properly. Tried to use ThreadLocal that did not work either.
You're mis-using Hibernate in some way that causes it to think you're updating or deleting objects from the database.
That's why calling flush() is throwing an exception.
One possibility: you're incorrectly "sharing" Session or Entities, via member field(s) of your servlet or controller. This is the main reason 'synchronized' would change your error symptoms.. Short solution: don't ever do this. Sessions and Entities shouldn't & don't work this way -- each Request should get processed independently.
Another possibility: unsaved-value defaults to 0 for "int" PK fields. You may be able to type these as "Integer" instead, if you really want to use 0 as a valid PK value.
Third suggestion: use Hibernate Session explicitly, learn to write simple correct code that works, then load the Java source for Hibernate/ Spring libraries so you can read & understand what these libraries are actually doing for you.
I also have been struggling with this exception, but when it continued to recur even when I put a lock on the object (and in a test environment, where I knew I was the only process touching the object), I decided to give the parenthetical in the stack trace its due consideration.
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect):
[com.rc.model.mexp.MerchantAccount#59132]
In our case it turned out that the mapping was wrong; we had type="text" in the mapping for one field that was a mediumtext type in the database, and it seems that Hibernate really hates that, at least under certain circumstances. We removed the type specification altogether from the mapping for this field, and the problem was resolved.
Now the weird thing is that in our production environment, with the supposedly problematic mapping in place, we do NOT get this exception. Does anybody have any idea why this might be? We are using the same version of MySQL - "5.0.22-log" (I don't know what the "-log" means) - in dev and production envs.
Here are 3 possibilities (as I do not know exactly, which kind of hibernate session handling you are using). Add one after another and test:
Use bi-directional mapping with inverse=true between parent object and child object, so the change in parent or child will get propagate to the other end of relation properly.
Add support for Optimistic Locking using TimeStamp or Version column
Use join query to fetch the whole object graph [ parent+children] together to avoid the second call altogether.
Lastly, if and only if nothing works:
Load the parent again by Id (you have that already) and populate modified data then update.
Life will be good! :)
This problem was something that I had experienced and was quite frustrating, although there has to be something a little odd going on in your DAO/Hibernate calls, because if you're doing a lookup by ID there is no reason to get a stale state, since that is just a simple lookup for an object.
First, make sure all your methods are annotated with #Transaction(required=true) // you'll have to look up the exact syntax
However, this exception is usually thrown when you try to make changes to an object that has been detached from the session it was retrieved from. The solution to this is often not simple and would require more code posted so we can see exactly what is going on; my general suggestion would be to create a #Service that performs these kinds of things within a single transaction