Grails

GORM Meta-property <manyOrOneToOneAssociationName>Id does not work on transient domain object instances

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Cannot Reproduce
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Given a class like:

class UserIdentifier {
static belongsTo = [user:User]
static mapping = { user lazy:true }

//...
}

Given a loaded UserIdentifier, I want to be able to get the ID of the "user" without Hibernate doing a select. I do this regularly in pure Java and it is a documented feature in Hibernate (see http://www.hibernate.org/118.html#A21). In Java you can do userIdentifier.getUser().getId() and the full proxy will not be initialized and no select will happen. It makes sense because the User ID is in the UserIdentifier table due to the belongsTo. In Grails, as soon as you do a userIdentifier.getUser() it does a select of the associated user.

Activity

Hide
Bob Tiernay added a comment -

This seems to return null in the case where the base object is not yet saved, but associations are set.

params['to.id'] = params.id
params['from.id'] = session.member.id
def feedback = new Feedback(params)
println feedback.fromId // prints null, but should print id
println feedback.from.id // prints actual value, as expected

I've tried step debugging through this issue and I'm seeing that a NoSuchMethodException is being thrown in

GrailsDomainConfigurationUtil.getAssociationIdentifier

public static Serializable getAssociationIdentifier(Object target, String propertyName, GrailsDomainClass referencedDomainClass) {
        String getterName = GrailsClassUtils.getGetterName(propertyName);

        try {
            Method m = target.getClass().getDeclaredMethod(getterName, EMPTY_CLASS_ARRAY);
            Object value = m.invoke(target, null);
            if(value != null && referencedDomainClass != null) {
                String identifierGetter = GrailsClassUtils.getGetterName(referencedDomainClass.getIdentifier().getName());
                m = value.getClass().getDeclaredMethod(identifierGetter, EMPTY_CLASS_ARRAY);
                return (Serializable)m.invoke(value, null);
            }
        } catch (NoSuchMethodException e) {
           // ignore
        } catch (IllegalAccessException e) {
           // ignore
        } catch (InvocationTargetException e) {
            // ignore
        }
        return null;
    }

I'm thinking this could be caused by the use of the constructor over a hibernate proxy as loaded from a Feedback.get(id) call.

At any rate, I've had to use the second form for now (feedback.from.id), although in this case I could have got a way with just using the parameter.

Show
Bob Tiernay added a comment - This seems to return null in the case where the base object is not yet saved, but associations are set.
params['to.id'] = params.id
params['from.id'] = session.member.id
def feedback = new Feedback(params)
println feedback.fromId // prints null, but should print id
println feedback.from.id // prints actual value, as expected
I've tried step debugging through this issue and I'm seeing that a NoSuchMethodException is being thrown in GrailsDomainConfigurationUtil.getAssociationIdentifier
public static Serializable getAssociationIdentifier(Object target, String propertyName, GrailsDomainClass referencedDomainClass) {
        String getterName = GrailsClassUtils.getGetterName(propertyName);

        try {
            Method m = target.getClass().getDeclaredMethod(getterName, EMPTY_CLASS_ARRAY);
            Object value = m.invoke(target, null);
            if(value != null && referencedDomainClass != null) {
                String identifierGetter = GrailsClassUtils.getGetterName(referencedDomainClass.getIdentifier().getName());
                m = value.getClass().getDeclaredMethod(identifierGetter, EMPTY_CLASS_ARRAY);
                return (Serializable)m.invoke(value, null);
            }
        } catch (NoSuchMethodException e) {
           // ignore
        } catch (IllegalAccessException e) {
           // ignore
        } catch (InvocationTargetException e) {
            // ignore
        }
        return null;
    }
I'm thinking this could be caused by the use of the constructor over a hibernate proxy as loaded from a Feedback.get(id) call. At any rate, I've had to use the second form for now (feedback.from.id), although in this case I could have got a way with just using the parameter.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: