-->
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.  [ 5 posts ] 
Author Message
 Post subject: Newbie question. Hibernate couldnt resolve property
PostPosted: Sun Aug 13, 2006 9:04 am 
Newbie

Joined: Sun Aug 13, 2006 8:38 am
Posts: 3
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:3.1

I have following class:
Code:
/**
* Created by IntelliJ IDEA.
* @hibernate.class
*/

public class User implements Serializable  {
    private long    userID;
    private UserVersion baseUserVersion;

    ..... some more user fields like firsName, birthday e.tc

    /**
     * @hibernate.id generator-class="identity"
    */
    public long getUserID() {
        return userID;
    }

    public void setUserID(long userID) {
        this.userID = userID;
    }
   
   /**
     * @hibernate.many-to-one
     * class="com.btf.um.entity.UserVersion"
     * column="baseUserVersionID"
     */
    public UserVersion getBaseUserVersion() {
        return baseUserVersion;
    }

    public void setBaseUserVersion(UserVersion baseUserVersion) {
        this.baseUserVersion = baseUserVersion;
    }


For storing modification on user table i have created subclass UserVersion:
Code:
/**
* Created by IntelliJ IDEA.
* @hibernate.class
*/
public class UserVersion extends User{
    private long               userVersionID;
    private UserVersion    childVersion;
    private User               actualUser;

    public UserVersion() {
    }

    public UserVersion(User actualUser) {
        this.actualUser = actualUser;
        setUser(actualUser);
    }

    /**
    * @hibernate.many-to-one
    * class="com.btf.um.entity.User"
    * column="userID"
    * not-null="true"
    */
    public User getActualUser() {
        return actualUser;
    }

    public void setActualUser(User actualUser) {
        this.actualUser = actualUser;
    }

    /**
    * @hibernate.many-to-one
    * class="com.btf.um.entity.UserVersion"
    * column="childVersionID"
    */
    public UserVersion getChildVersion() {
        return childVersion;
    }

    public void setChildVersion(UserVersion childVersion) {
        this.childVersion = childVersion;
    }

    /**
    * @hibernate.id generator-class="identity"
    */
    public long getUserVersionID() {
        return userVersionID;
    }

    public void setUserVersionID(long userVersionID) {
        this.userVersionID = userVersionID;
    }

    public User getUser() {
        return this;
    }

    public void setUser(User user) {
        copyObjectValues(this, user);
    }
}


Hibernate works absolutely decent on inserting or updating data in those tables, but i`m getting strange exception on excetuting following procedure

Code:
public List selectOtherUsersForPassport(String passportNum, String passportSeries, long userID) {
         return getHibernateTemplate().find("from User u where u.passportNum = ? AND u.passportSeries=? AND u.userID!=? and u.deleted = false",
                new Object[] {passportNum, passportSeries, userID});
    }

Exception:
Code:
org.springframework.orm.hibernate3.HibernateQueryException: could not resolve property: userID of: com.btf.um.entity.UserVersion [
from com.btf.um.entity.UserVersion u where u.passportNum = ? AND u.passportSeries=? AND u.userID!=? and u.deleted = false]; nested
exception is org.hibernate.QueryException: could not resolve property: userID of: com.btf.um.entity.UserVersion [from com.btf.um.
entity.UserVersion u where u.passportNum = ? AND u.passportSeries=? AND u.userID!=? and u.deleted = false]
Caused by: org.hibernate.QueryException: could not resolve property: userID of: com.btf.um.entity.UserVersion [from com.btf.um.ent
ity.UserVersion u where u.passportNum = ? AND u.passportSeries=? AND u.userID!=? and u.deleted = false]
        at org.hibernate.persister.entity.AbstractPropertyMapping.throwPropertyException(AbstractPropertyMapping.java:43)
        at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:37)
        at org.hibernate.persister.entity.BasicEntityPersister.toType(BasicEntityPersister.java:1094)
        at org.hibernate.hql.ast.FromElementType.getPropertyType(FromElementType.java:273)
        at org.hibernate.hql.ast.FromElement.getPropertyType(FromElement.java:349)
        at org.hibernate.hql.ast.DotNode.getDataType(DotNode.java:474)
        at org.hibernate.hql.ast.DotNode.prepareLhs(DotNode.java:208)
        at org.hibernate.hql.ast.DotNode.resolve(DotNode.java:166)
        at org.hibernate.hql.ast.FromReferenceNode.resolve(FromReferenceNode.java:87)
        at org.hibernate.hql.ast.FromReferenceNode.resolve(FromReferenceNode.java:83)
        at org.hibernate.hql.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:463)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:863)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:3713)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:3215)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:1405)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:1333)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:1330)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:599)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:404)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:201)
        at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:151)
        at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:189)
        at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:130)
        at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:83)
        at org.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:427)
        at org.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:884)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:834)
        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:74)
        at org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:837)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:366)
        at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:828)
        at com.btf.um.dao.hbm.UserDaoImpl.selectOtherUsersForPassport(UserDaoImpl.java:101)
        at com.btf.um.service.UMService.selectOtherUsersForPassport(Unknown Source)
        at com.btf.um.service.UMService$$FastClassByCGLIB$$585ae255.invoke(<generated>)
        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
        at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:709)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:100)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:647)
        at com.btf.um.service.UMService$$EnhancerByCGLIB$$414d6173.selectOtherUsersForPassport(<generated>)
        at com.btf.transfer.web.PayWizardController.referenceData(Unknown Source)
        at org.springframework.web.servlet.mvc.AbstractWizardFormController.referenceData(AbstractWizardFormController.java:267)
        at org.springframework.web.servlet.mvc.AbstractFormController.showForm(AbstractFormController.java:557)
        at org.springframework.web.servlet.mvc.AbstractWizardFormController.showPage(AbstractWizardFormController.java:351)
        at org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.jav
a:513)
        at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:250)


I cant realize why hibernate uses entity "com.btf.um.entity.UserVersion" instead of "com.btf.um.entity.User" and this is problem which brings excpetion i guess because procedure works fine if there is no "u.userID" property in query string.

Any help would be usefull. Thanx!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 12:34 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
It's because UserVersion extends User. Have you read anything about polymorphism? There is a difference between the "is-a" and "has-as-a-role" relationships, and hibernate fully understands this difference. By telling hibernate that UserVersion is-a User, hibernate now knows that all UserVersions have a UserID as their primary key. Which of course they don't: they have UserVersionID as their primary key, UserID is an FK to a different table, User.

Make UserVersion not extend User. You can implement your relationship either as "UserVersion has-as-a-role User" (which looks odd to me), or use one of the more intuitive relationships like User has-a collection-of UserVersion, or UserVersion has-a User.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 5:16 am 
Newbie

Joined: Sun Aug 13, 2006 8:38 am
Posts: 3
Thanks for reply tenwit!

Aye i have read about polymorphism in hibernate in hibernate reference and hibernate in action (Can u suggest any other books to read about?) and found only this way to achive my aim - storing data of user modification in other table then User for keeping unique ID for each user in system and dont correct source code of UserVersion on each modification in User source code. (Other solution for me was creation recursive structure of User table. but so sad that MySql and HQL dont support it). But i gonna try ur suggestions as well.

At this moment, i solved my problem via adding property
Code:
    /**
    * @hibernate.property
    * not-null = "true"
    */
    public long getUserID() {
        return super.getUserID();
    }

    public void setUserID(long userID) {
       super.setUserID(userID);
    }


but its sorta ugly cause this solution breaks integrity between User entity and userID field in UserVersion entity.


Umm, have i realized right following things?
If we have parrent entity User and N child entities of User each in diffrent tables, hibernate gonna search data in all N+1 (N-child + parrent) tables when i execute the query like "from u User where u.blabla = ohoh"?
And if my assumption is right is there any way to force hibernate doesnt do so cause in this situation i dont really need polymorphism on ORM level but need it on object model level.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 8:48 am 
Newbie

Joined: Sun Aug 13, 2006 8:38 am
Posts: 3
Ok, i have sorta figured out the decision and in case it might be usefull for someone im gonna explain it :)

Solution 1: setting polymorphism property to explicit in User entity
e.g
Code:
/**
* @hibernate.class
* polymorphism = "explicit"
*/


Solution 2: creating unmapped parrent class for User and UserVersion
Code:

public class AbstractUser {
... User properties...
}

<--------------------------------- user -------------------------------->

/**
* @hibernate.class
*/
public class User extends AbstractUser{
  private long              userID;
  private UserVersion   baseUserVersion;

    /**
     * @hibernate.id generator-class="identity"
    */
    public long getUserID() {
        return userID;
    }

    public void setUserID(long userID) {
        this.userID = userID;
    }

    /**
     * @hibernate.many-to-one
     * class="com.btf.um.entity.UserVersion"
     * column="baseUserVersionID"
     */
    public UserVersion getBaseUserVersion() {
        return baseUserVersion;
    }

    public void setBaseUserVersion(UserVersion baseUserVersion) {
        this.baseUserVersion = baseUserVersion;
    }
<------------------------------------ UserVersion -------------------------->
/**
* @hibernate.class
*/
public class UserVersion extends AbstractUser{
   private long            userVersionID;
   private User            actualUser;
   private UserVersion childUserVersion;
 
    /**
    * @hibernate.many-to-one
    * class="com.btf.um.entity.User"
    * column="userID"
    * not-null="true"
    */
    public User getActualUser() {
        return actualUser;
    }

    public void setActualUser(User actualUser) {
        this.actualUser = actualUser;
    }

    /**
    * @hibernate.many-to-one
    * class="com.btf.um.entity.UserVersion"
    * column="childVersionID"
    */
    public UserVersion getChildVersion() {
        return childVersion;
    }

    public void setChildVersion(UserVersion childVersion) {
        this.childVersion = childVersion;
    }

    /**
    * @hibernate.id generator-class="identity"
    */
    public long getUserVersionID() {
        return userVersionID;
    }

    public void setUserVersionID(long userVersionID) {
        this.userVersionID = userVersionID;
    }

}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 5:36 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
The only other hibernate reference that I use is the wiki area on the hibernate site. The refdocs are my main source: HIA is good for theory, but it falls behind in the implementation details, as hibernate is published a lot more frequently than the book :)

If the getUserID/setUserID thing risks breaking integrity, you can change it to getUser/setUser and use many-to-one associations: that would be a better solution.

The abstract superclass is a good solution, but it still seems to me that User and UserVersion should not be in a class hierarchy, they should be related via an assoication. However, I don't know anything about the internals or reasons behind your choice of solution, so I can't say that it's wrong.

If you want an object to be loaded with its related/collected objects in a single select, then you can specify the fetch mode in your query. You need left outer join, so that if associated entity is null, or there's an empty collection, you still get your main object. The syntax is
Code:
from User u left outer join fetch u.UserVersion where u.blabla = ohoh
The "outer" keyword is optional.

_________________
Code tags are your friend. Know them and use them.


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