views:

2101

answers:

5

I have been working with hibernate/JPA on JBoss for some months now and have one question that I can't find an answer or solution for.

It seems like when creating new entity beans I'm not able to do a query before I at least have called EntityManager.persist(entityBean), or else I get the following error:

TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing

An example:

Job job = new Job();
Collection<Task> tasks = job.getTasks();
//entityManager.persist(job);
ActionPlan actionPlan = (ActionPlan) entityManager.createNamedQuery("ActionPlan.findByCommand").
                setParameter("type", RunOperation.Install).getSingleResult();
Task task = Task.getTask(actionPlan);
task.setActionPlan(actionPlan);
tasks.add(task);
task.setJob(job);

My problem is that I can't call createNamedQuery without first persisting 'job' (the line that is commented out). ActionPlan has a relation to Job, but the NamedQuery (findByCommand) does not join on Job. What bothers me is that I need to persist Job in order to query the database, when the new created Job is not even interesting in this context.
Moving the call to persist() to the end of the snippet yields the above mentioned error.

I'm aware that the object I'm working on is not persisted, but persisting makes it impossible to rollback if an error occurs.

I believe there is a solution for this, so if someone has the answer I would be very thankful. What am I missing?

+2  A: 

It seems logical that you cannot query for something which is not in the database yet, no? What you can do is to start using transactions. In a simple case your session will have one transaction which will be open until you close your session. At that moment transaction will be commited and all your changes will be persisted. All you need is to rollback your transaction in case of error.

P.S. Here on the bottom you can find "A typical transaction should use the following idiom".

Georgy Bolyuba
A: 

I am aware that I can't query what has not yet been persisted - and this is not the case either. What I want to find is other Entity beans. Not just the same type, but any type of the Entity beans that I have. And then I get the TransientObjectException.

Did I mention I use JBoss? I believe that using J2EE and JPA the server is in control of my transactions, and the last I want to do is interfere with it?! So for me, besides using requiresNew, etc. I don't mess with transactions - the server does.

Maybe I should move the hibernate tag, because actually I'm using JPA - JBoss uses hibernate. So please relate to that in any code examples.

homaxto
Georgy Bolyuba
an email. bolyuba at gmail dot com. But one thing I can tell you right now: "I don't mess with transactions - the server does." is a bad approach. Even if you do use declarative transaction demarcation, you should know exactly what is going on.
Georgy Bolyuba
Georgy, I really appreciate your help - don't get me wrong. I think I have been to brief in my question so I have added an example. If it still is not clear to you what I mean let's take it to the second level :)
homaxto
A: 

Even if you persist object you still can rollback it. Only after invoking flush on EntityManager would case synchronizing to the underlying database.

A: 

Well I think that the answers and reading up a bit in the Java EE 5Tutorial has given me the right answer.

On the contrary of my belief, persist() does not flush to the database, it only moves the Entity bean to the persisted state. What tricked me is that I noticed that after calling persist the entity actually gets persisted to the database anyway (and maybe the word 'save' in the error message). I took this as flush was called ending my transaction, but if I get themalkolm right, I am still able to rollback - by myself or by the server on an exception.

So the conclusion I make is; persist should just be called, whenever a new entity is made, as long as it is not in relation to another entity already persisted.
Then the transaction is maintained and the server likes you a little bit more ;)

What is left her is that I still don't understand why I am not able to make a query without everything being in a persisted state.

homaxto
A: 

What kind of relation has ActionPlan to Job? And what actually "findByCommand" do? Show some more code :)