-->
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.  [ 14 posts ] 
Author Message
 Post subject: Simple problem...
PostPosted: Thu Apr 12, 2007 11:08 am 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
I know this is a simple problem, but I have read a lot of documentation and altho the solution looks trivial, it doesn't work for me :\

So here it is, I have User and Authority classes map to their respective table and a table User_Authority to hold a many-to-many association. I have a some Authority objects already persisted in my database and when I create a new User, I assign to it an existing Authority object. The problem is, when I save this new User, Hibernate also tries to insert the authority object even tho it's already there in the database.

I use a java.lang.Long objet for my Authority id and tried to set the unsaved-value property but it doesn't work. I also tried to overid the equals() and hashCode() even tho I don't think that is the problem. What else should I check ?

Thank you.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 12, 2007 11:40 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Post your code that gets the Authority and the code that saves the User.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 12, 2007 1:47 pm 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
There it is, it's very simple

Transaction tx = session.beginTransaction();

Authority authority= (Authority )session.get("org.ab.lvel.model.Authority ", new Long(1));
user.addAuthority(authority);
session.save(user);

tx.commit();


Here is my User.hbm.xml

...

<set name="roles" table="USER_AUTHORITY" cascade="save-update" >
<key column="ID" />
<many-to-many class="org.ab.lvel.model.Authority" column="AID" />
</set>



and my Authority.hbm.xml

<class name="org.ab.lvel.model.Authority" table="AUTHORITY" schema="lvel">
<id name="aid" unsaved-value="none">
<generator class="increment" />
</id>

<property name="role" column="ROLE" />

</class>


Is something wrong ? Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 12, 2007 4:34 pm 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Need to see the user.addAuthority() method. The unsaved-value is not necessary. I don't think the cascade is necessary on the set, as it will automatically cascade to the join table.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 12, 2007 5:05 pm 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
Here it is :

...

private Long id;

private Set<Authority> roles = new HashSet<Authority>();

...

public void addAuthority(Authority authority) {
roles.add(authority);
}


Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 4:01 am 
Regular
Regular

Joined: Thu Dec 22, 2005 7:47 am
Posts: 62
Location: Czech Republic
hi,

you say the relation is many-to-many? are you sure you gave us the right mapping -- you have many end at the user table, but just a simple property in the authority table (not even a many-to-one, but simple property)?

I would expect st like there -- http://www.hibernate.org/hib_docs/reference/en/html/collections.html#collections-bidirectional -- note the many ends at both sides.

Also, the add method shoul be located at the 'parent end' -- you decide where to put the inverse keyword -- and should contain st like:

Code:
public void addUser(User user) {
  // add the authority to the user (user is the child end, this will not trigger the insert)
  user.getAuthorities().add(this);
  // add the user to the authority (this will trigger the insert, if authority is the parent end
  this.getUsers().add(user);
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 9:47 am 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
But that would make the association bidirectional, right ? Is there a way to have a unidirectional many-to-many association ?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 9:57 am 
Regular
Regular

Joined: Thu Dec 22, 2005 7:47 am
Posts: 62
Location: Czech Republic
of course, you may have unidirectional associations.

in that case, just leave out one of the many-to-many declarations (but you have a role property instead of many-to-many)

see http://www.hibernate.org/hib_docs/reference/en/html/collections.html#collections-ofvalues

regards, m.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 10:30 am 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
thanks for the quick answer. But now when I create a new User and assign it an Authority, the database is updated correctly but I have this exception right after :

SEVERE: Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: org.ab.lvel.model.Authority


And the code I use the save my User is still :

Authority authority = (Authority)session.get("org.ab.lvel.model.Authority", new Long(1));
user.addAuthority(authority);
session.save(user);

I can use the cascade="save-update" attribute, but then I still have the problem where Hibernates try to insert the Authority object while it's already in the db.

Why won't hibernate see that the authority object I'm assigning is already in the db ?

Can anyone help me ? Thanks


Last edited by beaupre_a on Fri Apr 13, 2007 10:49 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 10:47 am 
Regular
Regular

Joined: Thu Dec 22, 2005 7:47 am
Posts: 62
Location: Czech Republic
Pls, give me current mapping, stack trace and a bit more lines of code, if possible.

This is quite frequent error, in combination with collections i would say you have a wrong cascade setting, though your code looks fine.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 11:00 am 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
Ok, first I'm using spring, so maybe that's where the problem is... Second, in the following I renamed "Authority" to "Role"..

(btw I'm sorry, I don't know how to have a nice display of my code)

I use the same mapping files showed previously.


Here's the complete method accessing hibernate, it uses a Spring HibernateTemplate to access hibernate.

public void addUser(final User user) {
getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session) {

Role role = (Role)session.get("org.ab.lvel.model.Role", new Long(1));
user.addRole(role);
session.save(user);

return null;
}
});
}

And my complete stack trace is (when is use the cascade="save-update" attribute)
org.hibernate.exception.ConstraintViolationException: could not insert: [org.ab.lvel.model.Role]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2263)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:388)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:363)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:328)
at org.ab.lvel.persistence.dao.hibernate.UserDaoHibernate.addUser(UserDaoHibernate.java:89)
at org.ab.lvel.model.service.UserServiceImpl.addUser(UserServiceImpl.java:50)
at org.ab.lvel.web.action.SignupAction.signup(SignupAction.java:83)
at org.ab.lvel.web.action.SignupAction.executeAction(SignupAction.java:43)
at org.ab.lvel.web.action.CommonAction.execute(CommonAction.java:51)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:264)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:217)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:229)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:148)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL070413103716641' defined on 'ROLE'.
at org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:101)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:23)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2243)
... 58 more



Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 11:27 am 
Regular
Regular

Joined: Thu Dec 22, 2005 7:47 am
Posts: 62
Location: Czech Republic
ad code formatting -- use [.code.] ... [/.code.] without those dots around your code

ad exception -- you have an exception

Code:
Caused by: java.sql.SQLException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL070413103716641' defined on 'ROLE'


what is the uniq constrainet you are violating? how do you assign ids?

what is the purpose of

Code:
<property name="role" column="ROLE" />


in your User mapping? -- if you intend to reference the Role class you should use many-to-many or many-to-one or one-to-one (many-to-many in your case i would guess -- one user can have multiple roles and one role can have multiple users, is it so? and probably bidirectional association)

try this:

Code:
<set name="roles" table="USER_AUTHORITY"
  cascade="save-update"
  inverse="true" >
<key column="ID" />
<many-to-many class="org.ab.lvel.model.Role" column="AID" />
</set>


anyway, the mapping files has probably changed a bit, it would be nice if you really post the current version. it would save me time to guess.

regards, m.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 11:58 am 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
Ok, this is my Role.hbm.xml

Code:
<class name="org.ab.lvel.model.Role"
      table="ROLE"
      schema="lvel">
   <id name="rid" unsaved-value="none">
      <generator class="increment" />
   </id>
      
   <property name="role" column="ROLE" />      
</class>



And this is, my User.hbm.xml

Code:
<class name="org.ab.lvel.model.User"
      table="USERS"
      schema="lvel">
   <id name="id" column="ID">
      <generator class="increment" />
   </id>
      
   <property name="username" column="USERNAME" />
   
   <set name="roles" table="USER_ROLE"
         cascade="save-update"
         inverse="true">
      <key column="ID" />
      <many-to-many class="org.ab.lvel.model.Role" column="RID" />
   </set>
</class>


Here is the SQL code generated by Hibernates
Hibernate: select role0_.rid as rid0_0_, role0_.ROLE as ROLE0_0_ from lvel.ROLE role0_ where role0_.rid=?
Hibernate: select max(ID) from USERS
Hibernate: select max(rid) from ROLE
Hibernate: insert into lvel.USERS (USERNAME, ID) values (?, ?)
Hibernate: insert into lvel.ROLE (ROLE, rid) values (?, ?)

The constraint violation comes from the fact that hibernates try to insert the Role object, but it's already in the ROLE table, causing a primary key violation.

Am I doing something wrong ? Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 13, 2007 2:29 pm 
Newbie

Joined: Thu Apr 12, 2007 10:50 am
Posts: 8
I'm soo sorry, I just found my dumb mistake, can't beleive it, I was assigning another Role from previous declaration, thanks for trying to help me.


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