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.  [ 7 posts ] 
Author Message
 Post subject: subclass & transaction
PostPosted: Sat Apr 07, 2007 2:13 pm 
Newbie

Joined: Thu Mar 15, 2007 10:03 pm
Posts: 6
Hi everyone!

I have a problem. I have classes User, and Marker which is a subclass of User. I have tables User and Marker.

In a use case, I want to make a User become a Marker, so I have to insert a Marker for the existing User. Then, I want to load the newly created Marker.

I created User and joined-subclass Marker. To be able to insert a Marker alone, I created MarkerOnly which is only the content of table Marker. So I can make an existing User a Marker. (see below)

The problem: when, in the same transaction, I create a MarkerOnly for an existing User and I load the Marker right after, the supposedly loaded marker is always null...

When I do the exact same operations outside a transaction (ie. one transaction per operation), everything works fine.

Does anyone have an idea to help me, please?

Thanks in advance!

Here are some informations:


Hibernate version: 3.2.2

Mapping documents:

User.hbm.xml :

Code:
<hibernate-mapping>
   <class name="User" table="user">
      <id name="userId" type="int">
         <column name="user_id" />
         <generator class="native" />
      </id>
      <property name="username" type="string">
         <column name="username" length="45" not-null="true" />
      </property>
      <one-to-one name="markerOnly" class="MarkerOnly" />
      <joined-subclass name="Marker" table="marker" lazy="false">
         <key column="user_id_fk" not-null="true" />
         <property name="markerStatus" type="string">
            <column name="status" length="19" />
         </property>
      </joined-subclass>
   </class>
</hibernate-mapping>


MarkerOnly.hbm.xml :

Code:
<hibernate-mapping>
   <class name="MarkerOnly" table="marker">
      <id name="userId" type="int">
         <column name="user_id_fk" />
      </id>
      <property name="markerStatus" type="string">
         <column name="status" length="19" />
      </property>
   </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

Code:
// Does the Marker row exist for this user?
// this performs a find("from Marker where userId=?", ...)
Marker marker = this.markerDAO.getMarker(user.getUserId());

// If not, create MarkerOnly
if (marker == null) {
   MarkerOnly markerOnly = new MarkerOnly(user.getUserId());
   // This performs a save...
   this.markerOnlyDAO.create(markerOnly);
}

// Get the whole marker
marker = this.markerDAO.getMarker(user.getUserId());

// marker is ALWAYS null!!  But I just created it!


Full stack trace of any exception that occurs:

No exception

Name and version of the database you are using:

MySQL 5.0.37


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 08, 2007 6:18 am 
Newbie

Joined: Sun Oct 08, 2006 8:03 am
Posts: 14
Do you see any insert statements in the log?
Is there any entry in the Marker table?

John.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 08, 2007 11:10 pm 
Newbie

Joined: Thu Mar 15, 2007 10:03 pm
Posts: 6
john.yesberg wrote:
Do you see any insert statements in the log?
Is there any entry in the Marker table?

John.


Hi, thanks for the reply John.

Here is the log information for the insertion of MarkerOnly (table marker).

Code:
2007-04-08 22:45:12 org.hibernate.event.def.AbstractSaveEventListener performSaveOrReplicate
LE PLUS FIN: executing insertions
2007-04-08 22:45:12 org.hibernate.persister.entity.AbstractEntityPersister insert
LE PLUS FIN: Inserting entity: [com.***.***.business.persistence.MarkerOnly#2]
2007-04-08 22:45:12 org.hibernate.jdbc.AbstractBatcher logOpenPreparedStatement
FIN: about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2007-04-08 22:45:12 org.hibernate.jdbc.AbstractBatcher log
FIN: insert into ***.marker (marker_status, user_id_fk) values (?, ?)
2007-04-08 22:45:12 org.hibernate.jdbc.AbstractBatcher getPreparedStatement
LE PLUS FIN: preparing statement
2007-04-08 22:45:12 org.hibernate.persister.entity.AbstractEntityPersister dehydrate
LE PLUS FIN: Dehydrating entity: [com.***.***.business.persistence.MarkerOnly#2]
2007-04-08 22:45:12 org.hibernate.type.NullableType nullSafeSet
LE PLUS FIN: binding null to parameter: 1
2007-04-08 22:45:12 org.hibernate.type.NullableType nullSafeSet
LE PLUS FIN: binding '2' to parameter: 2
2007-04-08 22:45:12 org.hibernate.jdbc.BatchingBatcher doExecuteBatch
FIN: Executing batch size: 1
2007-04-08 22:45:12 org.hibernate.jdbc.AbstractBatcher logClosePreparedStatement
FIN: about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2007-04-08 22:45:12 org.hibernate.jdbc.AbstractBatcher closePreparedStatement
LE PLUS FIN: closing statement


I can't see the row inserted in table marker, because the transaction is rolled back because of the marker being null...

I guess I am going to try to commit the transaction instead of rolling it back just to make sure the marker row has been inserted.

Any other advice? Thank you!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 08, 2007 11:29 pm 
Expert
Expert

Joined: Tue Jan 30, 2007 12:45 am
Posts: 283
Location: India
Hi Kexkey,

Try session.flush(); after create or update.That might work.


post implementation of this.markerDAO.getMarker(user.getUserId()); That may help us to dig it out.

_________________
Dharmendra Pandey


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 09, 2007 11:37 am 
Newbie

Joined: Thu Mar 15, 2007 10:03 pm
Posts: 6
dharmendra.pandey wrote:
Hi Kexkey,

Try session.flush(); after create or update.That might work.


post implementation of this.markerDAO.getMarker(user.getUserId()); That may help us to dig it out.


Hi! Thanks for your reply!

My getMarker implementation is quite straight forward.

Code:
public Marker getMarker(int userId) {
   List list = this.getHibernateTemplate().find("from Marker where userId=?", new Integer(userId));
   if (list.size() > 0) {
      return (Marker) list.get(0);
   } else {
      return null;
   }
}


I tried to add a flush after the create... like this:

Code:
public void create(MarkerOnly markerOnly) {
   this.getHibernateTemplate().save(markerOnly);
   this.getHibernateTemplate().flush();
}


and I got that exception:

Code:
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: Object with id: 1 was not of the specified subclass: com.***.***.business.persistence.Commissioner (loaded object was of wrong class class com.***.***.business.persistence.Marker); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: com.***.***.business.persistence.Commissioner (loaded object was of wrong class class com.***.***.business.persistence.Marker)


The thing is that User has subclasses of type Marker (table marker) and Commissioner (table commissioner), and that particular User (id=1) is a Marker *and* a Commissioner. It looks like when everything is committed in the DB, when I call getMarker, it loads the Marker correctly. But here, the marker row created via the MarkerOnly (which is not a Marker class or subclass) create method, doesn't seem to be found until the transaction is committed.

That is the problem, actually. Hibernate loads that User and find a Commissioner for that User but not a Marker, so it throws that exception. I guess that happens because MarkerOnly is not associated with Marker for Hibernate's point of view. That makes it a completely independant object and Hibernate doesn't link it to Marker.

I don't know if everything I just said makes sense. I guess so. Maybe Hibernate just doesn't support that kind of operations and associations between different objects pointing to the same tables...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 10, 2007 6:15 am 
Newbie

Joined: Sun Oct 08, 2006 8:03 am
Posts: 14
If Marker and Commissioner are both separate subclasses of User, then you can't expect Hibernate to successfully cope with an object that is both. It really is a system than maps single-inheritance classes to tables.

(I understand that your class hierarchy doesn't allow you to have an object that is both a Marker and Commissioner.)

You may be able to modify your domain model. Instead of arguing that some users are markers, and some are commissioners, and some are both, you could say that a user may be associated with a certain marker role, and may be associated with a certain commissioner role. I'd use a nullable ManyToOne relationship in each case.

I don't think there'll be any loss in efficiency, and it will possibly be more maintainable code (ie. simpler to understand).

How does that sound to you?

John.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 10, 2007 9:44 am 
Newbie

Joined: Thu Mar 15, 2007 10:03 pm
Posts: 6
john.yesberg wrote:
If Marker and Commissioner are both separate subclasses of User, then you can't expect Hibernate to successfully cope with an object that is both. It really is a system than maps single-inheritance classes to tables.


You're right. When a User is a Commissioner *and* a Marker, and I load that User, an instance of Commissioner is created (because Commissioner joined-subclass is first in the hbm), not a Marker. But when I load a Commissioner or a Marker (instead of a User), it instantiates the good class correctly.

john.yesberg wrote:
(I understand that your class hierarchy doesn't allow you to have an object that is both a Marker and Commissioner.)


Actually, a Marker is a Marker, a Commissioner is a Commissioner, that's for sure. And that can make sense when I know that when I am working with Markers, I am not working with Commissioners. To know what the User is, I have UserRoles for that. But I make a distinction between the roles and the actual physical state of the user -- the role will control the access to the system functions, and the table row in commissioner will give the information about the "real" commissionner, which could give commissioner's access to a Marker by giving him the commissioner role...

Well, anyway, that's not the topic. :)

john.yesberg wrote:
You may be able to modify your domain model. Instead of arguing that some users are markers, and some are commissioners, and some are both, you could say that a user may be associated with a certain marker role, and may be associated with a certain commissioner role. I'd use a nullable ManyToOne relationship in each case.

I don't think there'll be any loss in efficiency, and it will possibly be more maintainable code (ie. simpler to understand).

How does that sound to you?


I didn't want to do that from the beginning, but I think that's the way I will have to make it work. I wanted to take advantage of the inheritance, the OO of the model... that's too bad.

I will have one-to-one relationships between User and Commissioner, User and Marker... Commissioner and Marker are not only roles, but contain also precious information that I didn't include in my previous posts.

Thank you John for your thoughts. More ideas are more than welcome! :)

Kexkey


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