Hibernate/JPA returns null when the underlying query has results

1.5k views Asked by At

I'm using JPA's entitymanager.find(T, pk) to find a record. This is in an existing app where entitymanager.find() is used successfully, but this is the first instance of using a composite primary key. Here is the entity class:

@Entity
@Table(name = "host_property", schema = "app")
@IdClass(HostPropertyPK.class)
public class HostProperty implements Serializable {
    @Id
    @Column(name = "host")
    private String host_;

    @Id
    @Column(name = "name")
    private String name_;

    @Column(name = "value")
    private String value_;

    private static final long serialVersionUID = 1L;

    /**
     * Java Persistence requires a no-argument constructor. Private so that only
     * JPA may use it.
     */
    private HostProperty() {
    }

    /**
     * Gets the associated host.
     * 
     * @return String containing the host
     */
    public String getHost() {
        return host_;
    }

    /**
     * Gets the property name.
     * 
     * @return String containing the property name
     */
    public String getName() {
        return name_;
    }

    /**
     * Gets the property value.
     * 
     * @return String containing the property value
     */
    public String getValue() {
        return value_;
    }

    /**
     * Gets the value as an int.
     * 
     * @return int containing the value parsed as an int
     */
    public int getIntValue() {
        return Integer.parseInt(value_);
    }

}

and the primary key class:

public class HostPropertyPK implements Serializable {
    private static final long serialVersionUID = 1L;
    @Column(name = "host")
    private String host_;

    @Column(name = "name")
    private String name_;

    /**
     * Java Persistence requires a no-argument constructor. Private so that
     * only JPA may use it.
     */
    @SuppressWarnings("unused")
    private HostPropertyPK() {
    }

    /**
     * Creates a host property primary key.
     * 
     * @param host String containing the host
     * @param propertyName String containing the property name
     */
    public HostPropertyPK(String host, String propertyName) {
        this.host_ = host;
        this.name_ = propertyName;
    }

    /**
     * Gets the host of this primary key.
     * 
     * @return String containing the host
     */
    public String getHost() {
        return host_;
    }

    /**
     * Gets the property name of this primary key.
     * 
     * @return String containing the property name
     */
    public String getPropertyName() {
        return name_;
    }

    @Override
    public int hashCode() {
        int code = 1;
        code = 31 * code + (host_ == null ? 0 : host_.hashCode());
        code = 31 * code +
            (name_ == null ? 0 : name_.hashCode());
        return code;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        if (!(o instanceof HostPropertyPK)) {
            return false;
        }
        HostPropertyPK other = (HostPropertyPK) o;
        if (host_ == null) {
            if (other.getHost() != null) {
                return false;
            }
        } else if (!host_.equals(other.getHost())) {
            return false;
        }
        if (name_ == null) {
            if (other.getPropertyName() != null) {
                return false;
            }
        } else if (!name_.equals(other.getPropertyName())) {
            return false;
        }
        return true;
    }
}

and the bean where I look up properties:

@Stateless
@Local(PropertyService.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class PropertyServiceBean implements PropertyService {
    @PersistenceContext(unitName="AppPersistence")
    private EntityManager entityManager_;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public HostProperty getHostProperty(String host, String propertyName) {        
        HostPropertyPK hostPropertyPK =
            new HostPropertyPK(host, propertyName);
        HostProperty prop = entityManager_.find(HostProperty.class, hostPropertyPK);
        System.out.println("FOUND HOST PROPERTY : " + prop);
        return prop;
    }

}

The value of prop at the point of System.out.println is null. I can confirm that the entity manager is not null by the fact execution reaches this point and also because I can capture the underlying query using XRebel:

select
    hostpr0_.host as host623_0_,
    hostpr0_.name as name623_0_,
    hostpr0_.value as value623_0_
from
    app.host_property hostpr0_
where
    hostpr0_.host = 'testhost'
    and hostpr0_.name = 'testprop'

I've confirmed that this query indeed returns a single row. However, Hibernate doesn't ultimately return my object, but rather a null! What could cause Hibernate to be able to generate the correct query, execute it, but not map an object from it?

0

There are 0 answers