-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Persisting/Synchronizing associations
PostPosted: Fri Jan 18, 2008 6:14 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
Hello:

I am very new to hibernate. Will try to describe my problem in very simple terms. May be I am doing something fundamentally wrong. Looking for direction in that respect.

I have a three tier application. I have the hibernate (pojo)classes, I have a DAO layer, Service Layer pojos (that map to the hibernate pojos), and the service layer.

My model is as follows- I have a unidirectional one-to-many relationship between three classes/entities. User -> Context ->Fact. User has a collection of Contexts. Each Context has a collection of Facts.

The service layer is the transaction boundary. It uses the DAO to load the user (and in turn the contexts and facts). I am then converting this user to a service layer
user.

In a separate service layer class I am manipulating the collections of the service layer user object. For example updating facts, adding facts, removing a fact from the collection.

Then when time comes, I want to persist the user (and in turn the contexts, facts) to the DB, I convert the service layer User to Hibernate layer User. And call the DAO to persist the user.

Any updates, insertion works fine. But removal of a fact from the facts collection in the context doesn't remove it from the database.

I did debug and made sure that the facts are indeed being removed from the collection.

There are no error/exceptions thrown. I don't see any Delete SQL statements, just update ones.

Thoughts?

Hibernate version: 3.2

Spring Framework : 2.5

Mapping documents:

User
<hibernate-mapping package="a.b.c">
<class name="User" lazy="false" table="USER">

<id name="userId" column="USER_ID" type="long">
<generator class="sequence">
<param name="sequence">_id_seq</param>
</generator>
</id>

<set name="allContexts" table="PZN_CONTEXT" cascade="all,delete-orphan">
<key column="USER_ID" not-null="true">
</key>
<one-to-many class="CorePznContext"/>
</set>

</class>
</hibernate-mapping>

Context
<hibernate-mapping package="a.b.c">
<class name="CorePznContext" table="PZN_CONTEXT" lazy="false">

<id name="contextId" column="CONTEXT_ID" type="long">
<generator class="sequence">
<param name="sequence">PznContext_id_seq</param>
</generator>
</id>

<property
name="contextName"
type="string"
column="CONTEXT_NAME"
length="100"
/>

<property
name="contextValue"
type="string"
column="CONTEXT_VALUE"
length="100"
/>
<set name="allFacts" table="PZN_FACTS" cascade="all,delete-orphan">
<key column="CONTEXT_ID" not-null="true">
</key>
<one-to-many class="CorePznFact"/>
</set>

</class>
</hibernate-mapping>

Fact
<hibernate-mapping package="a.b.c">
<class name="CorePznFact" lazy="false"
table="PZN_FACTS">
<id name="factId" column="FACT_ID" type="long">
<generator class="sequence">
<param name="sequence">PznFact_id_seq</param>
</generator>
</id>
<property
name="factName"
type="string"
column="FACT_NAME"
length="100"
/>
...
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 18, 2008 7:58 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
dsole,

Facts is an entity by itself, so removing it from a collection does not remove the record from the Facts table, just the association between a Fact and its parent.

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 18, 2008 10:50 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
gonzao_diaz,

Thanks for your reply.

So from what you are saying the association should be removed. i.e for that fact the context_id (i.e its parent id) should be made null? And if that would happen it would be an orphan and by the cascade="all, delete-orphan" it should be removed from the DB as well?

But this doesn't happen. The fact remains untouched and subsequent load user gets me back that fact.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 19, 2008 1:31 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
I see...
How are you removing the Fact, in your code?

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 20, 2008 9:44 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
I am removing the fact from the collection using

factList.remove(key)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 21, 2008 11:46 am 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Your set property is called "allFacts", not factList.
Can you gve some more details about the client code you utilize to instantiate these classes and to delete a Fact from a parent?

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 21, 2008 12:16 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
Well, that is because I am removing or (not just removing but) doing any kind of manipulation on the service layer user object.

That is, I have a service layer SUser, SContext and SFact classes that correspond to (User, CorePznContext, CorePznFact) respectively.

So I have utility methods that basically convert CorePznContext, CorePznFact to service layer objects.

My question would be, all the operations that I am doing are disconnected from hibernate. Meaning I am doing all these operations on the service layer objects. How would hibernate know that a fact was removed?

Does this make sense?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 21, 2008 12:52 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
gonzao_diaz,

Would it make sense to make the association bi-directional? And when I am removing the fact from the collection set the parent id to be null? and that way it will be removed by delete-orphan attribute specified?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 21, 2008 4:50 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Quote:
My question would be, all the operations that I am doing are disconnected from hibernate. Meaning I am doing all these operations on the service layer objects. How would hibernate know that a fact was removed?


At some point your data-modifying code has to exist within a session, and be surrounded by a transaction. No DB modification will occur unless these 2 things happen.

In a managed environment (I use Spring), spring surrounds my methods with "interceptors" that create a transaction if none available, and keep the session alive between HTTP calls.

I don't know the topology of your project, or whether you are using hibernate or not, but getting this configured right is normally a big issue. (Then, you just copy it from one project to the next).

Since you are talking about working "disconnected" from a session, at some point you will have to have a real session respecting the above 2 conditions, and link your disconnected object with "session.update(obj)" or some other command.

Quote:
Would it make sense to make the association bi-directional? And when I am removing the fact from the collection set the parent id to be null? and that way it will be removed by delete-orphan attribute specified?


No, you should make the association bidirectional only if there is a business need for that, but it per se will not solve your persistence problem.

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 21, 2008 5:06 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
gonzao_diaz,

I think, I confused you a bit. I am using spring-hibernate. I do have the session factory bean defined in my spring hibernate config file. And I am using annotation based transactions.

The @transactional is defined in my service layer class where I do save/load user.

I have been battling with this problem for some time now and few questions come to my mind.

I have a Generic based DAO which does save load, delete operations. My UserDAO extended from this and just add a new look by userName(which is not the PK for the USer table).

1) My question would be all data access operations (for context, fact) will be through UserDAO or I would need a separate DAO for each one.
For business purposes none the two classes will be loaded/read by their own, they will always make a sense only when associated by a user.

2) All I need is an atomic action on the user. i.e update or delete, insert (contexts and facts) that is coming in the request. But currently it just ignores the facts/context are not in the saveUpdate request.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 22, 2008 4:16 pm 
Newbie

Joined: Fri Jan 18, 2008 5:14 pm
Posts: 7
I kind of have a hacked solution to the problem. Instead of using getHibernateTemplate.saveOrUpdate() I tried using getHibernateTemplate.merge. And that worked!

I know that both the methods are not same, but I tried all possible test cases, and it seemed to be working fine.

Merge might be more expensive, but I don't know hibernate enough to discuss the differences between these two.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.