openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Prud'hommeaux <mprud...@apache.org>
Subject Re: Funky Query from entityManager.find(Class,id)
Date Tue, 24 Apr 2007 18:48:26 GMT
Phill-

On Apr 24, 2007, at 11:42 AM, Phill Moran wrote:

> Maybe I am wrong here let me ask a clarifying question. When  
> executing a find on
> an object that has a related object (like this example) does  
> OpenJPA create one
> select statement and grab all fields for both objects then parse  
> the results to
> build both objects?

Whenever possible, yes. For all fetch=EAGER relations (which  
@OneToOne and @ManyToOne default to), OpenJPA will try to eagerly  
select all of the instances in as few statements as possible. Most of  
the time it will just be a single statement.

This is discussed in some detail at:

   http://incubator.apache.org/openjpa/docs/latest/manual/ 
manual.html#ref_guide_perfpack_eager


> I assumed it makes one select per object. So in this case I
> would get two selects (which I thought I saw).
>
> Phill
>
> -----Original Message-----
> From: Marc Prud'hommeaux [mailto:mprudhomapache@gmail.com] On  
> Behalf Of Marc
> Prud'hommeaux
> Sent: April 24, 2007 2:20 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: Funky Query from entityManager.find(Class,id)
>
> Phill-
>
>> It should not be selecting from two tables as it cannot create the
>> object. As I mentioned before (in the other thread) this causes the
>> looked for object to be null as if the object was not found. Here is
>> my call statement
>
> ManyToOne and OneToOne relations default to being eagerly fetched.
> You can override this by specifying fetch=LAZY in the @ManyToOne  
> annotation.
>
> That being said, I don't understand that problem. Are you saying  
> that the lookup
> fails because there is no related attributetype row? That shouldn't  
> prevent the
> lookup from happening, since we are using an outer join.
>
>
>
> On Apr 23, 2007, at 11:20 PM, Phill Moran wrote:
>
>> I posted this question before but I am now seeing it in several  
>> places
>> and can produce a test case for it. Here are two related classes
>> (one-to-
>> many) attribute
>> and attributeType, each with table/class inheritance.
>>
>>
>> Attribute class:
>> package ca.BidSpec.emall.categories;
>>
>> import javax.persistence.Basic;
>> import javax.persistence.CascadeType;
>> import javax.persistence.Column;
>> import javax.persistence.Entity;
>> import javax.persistence.Inheritance;
>> import javax.persistence.InheritanceType;
>> import javax.persistence.JoinColumn;
>> import javax.persistence.ManyToOne;
>> import javax.persistence.NamedQueries; import
>> javax.persistence.NamedQuery; import javax.persistence.Table;
>>
>> import ca.BidSpec.emall.commonServices.PrimaryKey;
>> import ca.BidSpec.emall.persistence.Persistable;
>>
>> @Entity
>> @Table(name = "attributes")
>> @NamedQueries( {
>> 		@NamedQuery(name = "AttributeFXPK", query = "SELECT a FROM
> Attribute
>> a WHERE a.id = :primaryKey"),
>> 		@NamedQuery(name = "AttributeFXDescription", query = "SELECT a
> FROM
>> Attribute a WHERE a.value = :description ORDER BY a.value") })
>> @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class
>> Attribute extends Persistable {
>>
>> 	private AttributeType type;
>>
>> 	private String value = "";
>>
>> 	/*
>> 	 * required for persistence
>> 	 */
>> 	private Attribute() {
>> 	}
>>
>> 	public Attribute(PrimaryKey pk) {
>> 		this.setPrimaryKey(pk);
>> 	}
>>
>> 	/**
>> 	 * @param pk
>> 	 *            this objects primary key
>> 	 * @param type
>> 	 *            this object attribute type
>> 	 * @param value
>> 	 *            the value for this attribute given it's type
>> 	 */
>> 	public Attribute(PrimaryKey pk, AttributeType type, String value) {
>> 		this.setPrimaryKey(pk);
>> 		this.setType(type);
>> 		this.setValue(value);
>> 	}
>>
>> 	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
>> CascadeType.MERGE })
>> 	@JoinColumn(name = "attributeTypeFK")
>> 	public AttributeType getType() {
>> 		return type;
>> 	}
>>
>> 	public void setType(AttributeType type) {
>> 		this.type = type;
>> 	}
>>
>> 	@Basic()
>> 	@Column(name = "value", nullable = false, length = 50)
>> 	public String getValue() {
>> 		return value;
>> 	}
>>
>> 	public void setValue(String value) {
>> 		this.value = value;
>> 	}
>> }
>>
>>
>> AttributeType Class
>> package ca.BidSpec.emall.categories;
>>
>> import javax.persistence.Basic;
>> import javax.persistence.Column;
>> import javax.persistence.Entity;
>> import javax.persistence.Inheritance;
>> import javax.persistence.InheritanceType;
>> import javax.persistence.NamedQueries; import
>> javax.persistence.NamedQuery; import javax.persistence.Table;
>>
>> import ca.BidSpec.emall.commonServices.PrimaryKey;
>> import ca.BidSpec.emall.persistence.Persistable;
>>
>> @Entity
>> @Table(name = "attributetype")
>> @NamedQueries( {
>> 		@NamedQuery(name = "AttributeTypeFXPK", query = "SELECT a FROM
>> AttributeType a WHERE a.id = :primaryKey"),
>> 		@NamedQuery(name = "AttributeTypeFXDescription", query = "SELECT
> a
>> FROM AttributeType a WHERE a.description = :description ORDER BY
>> a.description") })
>> @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class
>> AttributeType extends Persistable {
>> 	private String description = "";
>>
>> 	/*
>> 	 * required for persistence
>> 	 */
>> 	private AttributeType() {
>> 	}
>>
>> 	public AttributeType(PrimaryKey pk) {
>> 		this.setPrimaryKey(pk);
>> 	}
>>
>> 	public AttributeType(PrimaryKey pk, String description) {
>> 		this.setPrimaryKey(pk);
>> 		this.setDescription(description);
>> 	}
>>
>> 	@Basic()
>> 	@Column(name = "description", length = 50)
>> 	public String getDescription() {
>> 		return description;
>> 	}
>>
>> 	/*
>> 	 * Set this attribute type's description
>> 	 */
>> 	public void setDescription(String description) {
>> 		this.description = description;
>> 	}
>> }
>>
>> Persistable is my based persistable class of all Entities:
>>
>> package ca.BidSpec.emall.persistence;
>>
>> import java.io.Serializable;
>> import java.sql.Timestamp;
>> import java.util.Date;
>>
>> import javax.persistence.Basic;
>> import javax.persistence.Column;
>> import javax.persistence.Id;
>> import javax.persistence.MappedSuperclass;
>> import javax.persistence.Temporal;
>> import javax.persistence.TemporalType; import
>> javax.persistence.Transient;
>>
>> import ca.BidSpec.emall.commonServices.PrimaryKey;
>>
>> @MappedSuperclass
>> public abstract class Persistable implements Serializable {
>>
>> 	/**
>> 	 * Comment for <code>id</code> This is a persistable objects Primary
>> id
>> 	 */
>>
>> 	private String id;
>>
>> 	/**
>> 	 * User record last updated
>> 	 */
>>
>> 	private Timestamp lastUpdated = new Timestamp((new Date()).getTime
>> ());
>>
>> 	/**
>> 	 * @return Returns the persistable objects id.
>> 	 */
>> 	@Id
>> 	@Column(name = "id")
>> 	protected String getId() {
>> 		return this.id;
>> 	}
>>
>> 	protected void setId(String theId) {
>> 		this.id = theId;
>> 	}
>>
>> 	/**
>> 	 * @return this object id in a primary id object
>> 	 */
>> 	@Transient
>> 	public PrimaryKey getPrimaryKey() {
>> 		return new PrimaryKey(this.getId());
>> 	}
>>
>> 	/**
>> 	 * @param id
>> 	 *            The id to set.
>> 	 */
>> 	public void setPrimaryKey(PrimaryKey primaryKey) {
>> 		this.setId(primaryKey.getKey());
>> 	}
>>
>> 	/**
>> 	 * @return Returns the lastUpdated date for this object.
>> 	 */
>> 	@Basic
>> 	@Temporal(TemporalType.TIMESTAMP)
>> 	@Column(name = "lastUpdated")
>> 	public Timestamp getLastUpdated() {
>> 		return this.lastUpdated;
>> 	}
>>
>> 	public void setLastUpdated(Timestamp lastUpdated) {
>> 		this.lastUpdated = lastUpdated;
>> 	}
>>
>> 	public boolean equals(Object obj) {
>> 		if ((obj != null) && (obj instanceof Persistable)) {
>> 			if (((Persistable) obj).getId().equals(this.getId())) {
>> 				return true;
>> 			}
>> 		}
>> 		return false;
>> 	}
>>
>> 	public int hashCode() {
>> 		return this.getId().hashCode();
>> 	}
>>
>> Here is the query generated:
>>
>> 16360  TRACE  [main] openjpa.jdbc.SQL - <t 28346522, conn 30686131>
>> executing prepstmnt 17313093 SELECT t0.id, t0.lastUpdated, t1.id,
>> t1.lastUpdated, t1.description, t0.value FROM attributes t0 LEFT  
>> OUTER
>> JOIN attributetype t1 ON t0.attributeTypeFK = t1.id WHERE t0.id = ?
>> [params=(String) 111e3a22-728a-86ce-0126-11a7acec229a:0]
>>
>> It should not be selecting from two tables as it cannot create the
>> object. As I mentioned before (in the other thread) this causes the
>> looked for object to be null as if the object was not found. Here is
>> my call statement
>>
>> 		Attribute deleteObj = (Attribute)
>> categoryFactory.getObjectByPK(Attribute.class,
>> 				"111e3a22-728a-86ce-0126-11a7acec229a:0"); <-
> this ID exists in
>> the table
>> 		assertNotNull(deleteObj); <-- fails here
>>
>> getObjectBYPK is
>>
>> 	public Persistable getObjectByPK(Class<? extends Persistable>
>> objectTypeBeingSought, String pk) {
>> 		Persistable per = null;
>> 		per = (Persistable)
>> getEntityManager().find(objectTypeBeingSought, pk);
>> 		return per;
>> 	}
>>
>> }
>>
>> I think this may be a bug as I see it in several classes - but
>> frustratingly not all. Any suggestions
>>
>> Phill
>>
>


Mime
View raw message