Return-Path: Delivered-To: apmail-incubator-open-jpa-dev-archive@locus.apache.org Received: (qmail 66501 invoked from network); 24 Apr 2007 18:49:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 24 Apr 2007 18:49:02 -0000 Received: (qmail 95145 invoked by uid 500); 24 Apr 2007 18:49:09 -0000 Delivered-To: apmail-incubator-open-jpa-dev-archive@incubator.apache.org Received: (qmail 95114 invoked by uid 500); 24 Apr 2007 18:49:09 -0000 Mailing-List: contact open-jpa-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: open-jpa-dev@incubator.apache.org Delivered-To: mailing list open-jpa-dev@incubator.apache.org Received: (qmail 95105 invoked by uid 99); 24 Apr 2007 18:49:09 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Apr 2007 11:49:09 -0700 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (herse.apache.org: domain of mprudhomapache@gmail.com designates 66.249.82.233 as permitted sender) Received: from [66.249.82.233] (HELO wx-out-0506.google.com) (66.249.82.233) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Apr 2007 11:49:01 -0700 Received: by wx-out-0506.google.com with SMTP id i26so2733350wxd for ; Tue, 24 Apr 2007 11:48:40 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:mime-version:in-reply-to:references:content-type:message-id:content-transfer-encoding:from:subject:date:to:x-mailer:sender; b=mxBj8SMmRIGMQjxP7lSLKXAqwye//Ig7b9qj4WuupkgQUZoZDmTeIu3ZmKTISEdq8QkUJ+xVAvWLgd25TdM/YCCiXn5vH5MhVuJAoZjwMUz/iYUIYTRCUWGm+bQxj0B9ihBT0PTiug/lgFIGecxQUDKVsHpBEpk6g5jBS0r88qs= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:mime-version:in-reply-to:references:content-type:message-id:content-transfer-encoding:from:subject:date:to:x-mailer:sender; b=qDW8le+rgsbh1/coUzfqR2KfjXjLZuWABy8heb9oWHHdh3nsZwHvi4CdBhiJaORmhG5Lp5JAAgu04S+fO/zTzYoukFU6GEjewsJpdK6Gpjl1kC9Tcub1KqD+KCyJnfZBrHTXnN5s97xR7WGkL4Hy2l2dlURL/tN1m2EY5KNYqDw= Received: by 10.70.32.13 with SMTP id f13mr12996639wxf.1177440520687; Tue, 24 Apr 2007 11:48:40 -0700 (PDT) Received: from ?192.168.15.100? ( [66.248.222.34]) by mx.google.com with ESMTP id i35sm16849068wxd.2007.04.24.11.48.39; Tue, 24 Apr 2007 11:48:40 -0700 (PDT) Mime-Version: 1.0 (Apple Message framework v752.3) In-Reply-To: <001301c786a0$5c8bbea0$6601a8c0@tyan2400> References: <001301c786a0$5c8bbea0$6601a8c0@tyan2400> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Message-Id: <6FDE19EE-91F7-44DB-8789-08B2B3D8692C@apache.org> Content-Transfer-Encoding: 7bit From: Marc Prud'hommeaux Subject: Re: Funky Query from entityManager.find(Class,id) Date: Tue, 24 Apr 2007 11:48:26 -0700 To: open-jpa-dev@incubator.apache.org X-Mailer: Apple Mail (2.752.3) Sender: Marc Prud'hommeaux X-Virus-Checked: Checked by ClamAV on apache.org 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 id 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 - >> 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 >> 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 >> >