-->
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.  [ 12 posts ] 
Author Message
 Post subject: OneToMany bidirectional insert problem
PostPosted: Wed Jan 30, 2008 2:26 pm 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
Hi All,

I have a problem with a parent-children relationship.
I try to add an Event element on the many side but this isn't saved on db.

this is my code:

Event evento=new Event();
...
//Load the account from DB
Account account = accountManager.getAccount(1);
account.addEvent(evento);
//saveAccount() method execute the saveOrUpdate() using Spring HibernateDaoSupport
accountManager.saveAccount(account);

Hibernate version: 3.2.3.ga

Mapping documents:
@Entity
@Table(name="ev_accounts")
public class Account implements Serializable {

/* Private Fields */
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
...
@org.hibernate.annotations.CollectionOfElements()
@JoinTable(name="ev_authorities",joinColumns= @JoinColumn(name="account_id"))
@Column(name= "authority",nullable=false)
private Set<String> authorities = new HashSet<String>();

@OneToMany(mappedBy="account",cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})
private Set<Event> events = new HashSet<Event>();
...

public void addEvent(Event event){
event.setAccount(this);
events.add(event);
}
...
}


@Entity
@Table(name="ev_events")
public class Event implements Serializable {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
...
@Embedded
private EventLocation eventLocation;

@ManyToOne(targetEntity=it.urlandus.events.app.domain.Account.class)
@JoinColumn(name="account_id",nullable=false,updatable=false,insertable=false)
private Account account;
...
}

Debug level Hibernate log excerpt:

I use Spring wiht a GenericHibernateDao based on HibernateDaoSupport in order to manage objects.

Full stack trace of any exception that occurs:

when I call the saveOrUpdate() method on Account object I get no exception but the Event instance are not saved and in my log I see that only the update on account is made.

[org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
2008-01-30 19:05:37,710 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12017163377
2008-01-30 19:05:37,717 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Eagerly flushing Hibernate session
2008-01-30 19:05:37,717 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - processing flush-time cascades
2008-01-30 19:05:37,717 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - dirty checking collections
2008-01-30 19:05:37,717 DEBUG [org.hibernate.engine.CollectionEntry] - Collection dirty: [it.urlandus.events.app.domain.Account.events#1]
2008-01-30 19:05:37,723 DEBUG [org.hibernate.engine.Collections] - Collection found: [it.urlandus.events.app.domain.Account.authorities#1], was: [it.urlandus.events.app.domain.Account.authorities#1] (uninitialized)
2008-01-30 19:05:37,723 DEBUG [org.hibernate.engine.Collections] - Collection found: [it.urlandus.events.app.domain.Account.events#1], was: [it.urlandus.events.app.domain.Account.events#1] (initialized)
2008-01-30 19:05:37,726 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects
2008-01-30 19:05:37,726 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 0 (re)creations, 1 updates, 0 removals to 2 collections
2008-01-30 19:05:37,726 DEBUG [org.hibernate.pretty.Printer] - listing entities:
2008-01-30 19:05:37,726 DEBUG [org.hibernate.pretty.Printer] - it.urlandus.events.app.domain.Account{password=f5888d0bb58d611107e11f7cbc41c97a, lastname=Balcon, events=[it.urlandus.events.app.domain.Event#0], enabled=Y, firstname=Marco, username=marco, url=urllll, email=aa@aa.aa, authorities=<uninitialized>, id=1}
2008-01-30 19:05:37,732 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2008-01-30 19:05:37,732 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
2008-01-30 19:05:37,733 DEBUG [org.hibernate.SQL] -
update
ev_accounts
set
email=?,
enabled=?,
firstname=?,
lastname=?,
password=?,
url=?,
username=?
where
id=?
2008-01-30 19:05:37,734 DEBUG [org.hibernate.jdbc.AbstractBatcher] - Executing batch size: 1
2008-01-30 19:05:37,735 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2008-01-30 19:05:37,736 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
2008-01-30 19:05:37,736 DEBUG [org.hibernate.jdbc.ConnectionManager] - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2008-01-30 19:05:37,736 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources


Name and version of the database you are using:
mysql 5

many thanks for your help!


Top
 Profile  
 
 Post subject: Re: OneToMany bidirectional insert problem
PostPosted: Wed Jan 30, 2008 3:22 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
Two things:

1- Why are you putting updatable=false,insertable=false on the relation?

2- Have configured hibernate to use its own datasource within scope of a global transaction?



Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 4:37 pm 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
Hi,

1- This is a workaround in order to set the "inverse=true" on the manytoone side (because inverse property is not available on this side). I have tried without updatable=false,insertable=false but I have the same result.

2- this question is not clear for me and, may be, this is my problem :)

I think that my current behaviour is:

- the loading action accountManager.getAccount(1); is executed within a session
and the action accountManager.saveAccount(account); within a new one.

What I need to check in order to answer your question?

Many thanks,
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 4:39 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
icdevelop wrote:
1- This is a workaround in order to set the "inverse=true" on the manytoone side (because inverse property is not available on this side). I have tried without updatable=false,insertable=false but I have the same result.


Why do you want inverse=true on that side?


Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 4:47 pm 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
Because on Event I have the method setAccount and think that this configuration should prevent a double update on relation column.

I'm started from the good example on Hibernate in Action book (item - bids) but could be that I have bad understand.

Regard
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 4:51 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
icdevelop wrote:
Because on Event I have the method setAccount and think that this configuration should prevent a double update on relation column.

I'm started from the good example on Hibernate in Action book (item - bids) but could be that I have bad understand.

Regard
Marco


inverse=true indicates who owns a relation, and owning a relation means who puts the database values for the relation. In case of ManyToOne in your example, Event has to own the relation because it is the one that has the key in db but you have forced hibernate not to update that key. I do believe hibernate is ignoring the inverse=true on the OneToMany side and on the ManyToOne side it does not insert/update the value. Remove those things and set the correct inverse settings and you should be good.


Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 5:06 pm 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
Now I'm not at work, and I will run new tests tomorow but because you are so kind I have a question in order to do the correct changes: I think that is more "correct" (at semantic level) add event adding it to the property "events" Set of Account.

I want to do this with the convenient method

public void addEvent(Event event){
event.setAccount(this);
events.add(event);
}

on Account class.

In order to do this, in your opinion, what is the Annotation that I need to modify?

Many thanks,
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 30, 2008 5:11 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
I think you are mixing it up a little bit. The event object needs to have an instance of an account so that hibernate can save the relation in database. Having event in the account's set is good for saving by reachability. Both sides are good when you load the data and you want to traverse, but how you save the values does not have much with the annotations. I mean what you have now is good enough.


Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 31, 2008 7:02 am 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
ok,

I have understand that on the many side "updatable=false,insertable=false" was wrong.

The other issue was that with

@OneToMany(mappedBy="account",fetch=FetchType.EAGER,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})
private Set<Event> events = new HashSet<Event>();

on one side the cascade don't work.

If I use CascadeType.ALL

@OneToMany(mappedBy="account",fetch=FetchType.EAGER,cascade={CascadeType.ALL})
private Set<Event> events = new HashSet<Event>();

all work fine.

Do you have any idea about this?

Many thanks,
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 31, 2008 11:18 am 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
icdevelop wrote:
Do you have any idea about this?



What is the code by which you test this?


Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 31, 2008 1:28 pm 
Newbie

Joined: Sun Jun 11, 2006 10:24 am
Posts: 9
Hi,

I've resolved the problem.

I have to use the annotation
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.DELETE})

instead of the CascadeType.PERSIST, CascadeType.MERGE

because I use the Hibernate native and not JPA.

But now I've another problem ;(

With the lazy option

@OneToMany(mappedBy="account")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.DELETE})
private Set<Event> events = new HashSet<Event>();

when in my class I do

...
Account account = new Account();
account.addEvent(evento);
accountManager.saveAccount(account);
...

I receive an
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: it.urlandus.events.app.domain.Account.events, no session or session was closed

at the account.addEvent(evento); row.

so I've add an OpenSessionInViewInterceptor to prevent this:

<bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>

but now nothing happens! The insert of event don't work.
In my log I see only:

[org.hibernate.loader.Loader] - loading collection: [it.urlandus.events.app.domain.Account.events#1]
2008-01-31 18:29:01,252 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2008-01-31 18:29:01,253 DEBUG [org.hibernate.SQL] -
select
events0_.account_id as account11_1_,
events0_.id as id1_,
events0_.id as id1_0_,
events0_.account_id as account11_1_0_,
events0_.basePrice as basePrice1_0_,
events0_.email as email1_0_,
events0_.endDate as endDate1_0_,
events0_.city as city1_0_,
events0_.country as country1_0_,
events0_.location as location1_0_,
events0_.province as province1_0_,
events0_.startDate as startDate1_0_,
events0_.title as title1_0_
from
ev_events events0_
where
events0_.account_id=?
2008-01-31 18:29:01,284 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open ResultSet (open ResultSets: 0, globally: 0)
2008-01-31 18:29:01,284 DEBUG [org.hibernate.loader.Loader] - result set contains (possibly empty) collection: [it.urlandus.events.app.domain.Account.events#1]
2008-01-31 18:29:01,289 DEBUG [org.hibernate.loader.Loader] - result row: EntityKey[it.urlandus.events.app.domain.Event#11]
2008-01-31 18:29:01,334 DEBUG [org.hibernate.loader.Loader] - found row of collection: [it.urlandus.events.app.domain.Account.events#1]
2008-01-31 18:29:01,336 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close ResultSet (open ResultSets: 1, globally: 1)
2008-01-31 18:29:01,336 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2008-01-31 18:29:01,336 DEBUG [org.hibernate.engine.TwoPhaseLoad] - resolving associations for [it.urlandus.events.app.domain.Event#11]
2008-01-31 18:29:01,337 DEBUG [org.hibernate.engine.TwoPhaseLoad] - done materializing entity [it.urlandus.events.app.domain.Event#11]
2008-01-31 18:29:01,338 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] - 1 collections were found in result set for role: it.urlandus.events.app.domain.Account.events
2008-01-31 18:29:01,338 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] - collection fully initialized: [it.urlandus.events.app.domain.Account.events#1]
2008-01-31 18:29:01,338 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] - 1 collections initialized for role: it.urlandus.events.app.domain.Account.events
2008-01-31 18:29:01,338 DEBUG [org.hibernate.engine.StatefulPersistenceContext] - initializing non-lazy collections
2008-01-31 18:29:01,338 DEBUG [org.hibernate.loader.Loader] - done loading collection
2008-01-31 18:29:01,339 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1ef577d] for key [org.hibernate.impl.SessionFactoryImpl@6e056e] bound to thread [http-8080-Processor24]
2008-01-31 18:29:01,339 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1ef577d] for key [org.hibernate.impl.SessionFactoryImpl@6e056e] bound to thread [http-8080-Processor24]
2008-01-31 18:29:01,339 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Found thread-bound Session for HibernateTemplate
2008-01-31 18:29:01,342 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Not closing pre-bound Hibernate Session after HibernateTemplate

Many Thanks,
Marco


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 31, 2008 9:27 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
Please post this as a new question and embed your code in code tags for more readability. Unfortunately I don't know what that open session in view is so I might not be the best person to answer your question. Posting a new question will capture attention of other experts.



Farzad-


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 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.