You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Kevin Sutter <kw...@gmail.com> on 2012/02/24 16:56:33 UTC

Re: svn commit: r1293250 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/

Nice testcase names!  :-)  I like to see a sense of humor...

On Fri, Feb 24, 2012 at 7:53 AM, <jr...@apache.org> wrote:

> Author: jrbauer
> Date: Fri Feb 24 13:53:01 2012
> New Revision: 1293250
>
> URL: http://svn.apache.org/viewvc?rev=1293250&view=rev
> Log:
> OPENJPA-2141 fix and test for lazy embedded fields
>
> Added:
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml
>   (with props)
>
>  openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml
>   (with props)
> Modified:
>
>  openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
>
>  openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
>
>  openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
>
> Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=1293250&r1=1293249&r2=1293250&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> (original)
> +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> Fri Feb 24 13:53:01 2012
> @@ -1087,10 +1087,6 @@ public class JDBCStoreManager implements
>                     if (processed != eres)
>                         res.putEager(fms[i], processed);
>                 } else {
> -                    boolean lazyEmbeddable =
> fms[i].getValueMapping().isEmbedded() &&
> -                        fms[i].getEmbeddedMetaData() != null &&
> -                        fetch.requiresFetch(fms[i]) ==
> FetchConfiguration.FETCH_NONE;
> -                    if (!lazyEmbeddable)
>                         fms[i].load(sm, this, fetch.traverseJDBC(fms[i]),
> res);
>                 }
>             } finally {
>
> Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java?rev=1293250&r1=1293249&r2=1293250&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
> (original)
> +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
> Fri Feb 24 13:53:01 2012
> @@ -43,6 +43,7 @@ import org.apache.openjpa.jdbc.meta.Clas
>  import org.apache.openjpa.jdbc.meta.Embeddable;
>  import org.apache.openjpa.jdbc.meta.FieldMapping;
>  import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
> +import org.apache.openjpa.jdbc.meta.Joinable;
>  import org.apache.openjpa.jdbc.meta.RelationId;
>  import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
>  import org.apache.openjpa.jdbc.schema.Column;
> @@ -62,7 +63,9 @@ import org.apache.openjpa.kernel.StateMa
>  import org.apache.openjpa.kernel.StoreContext;
>  import org.apache.openjpa.lib.util.Localizer;
>  import org.apache.openjpa.meta.ClassMetaData;
> +import org.apache.openjpa.meta.FetchGroup;
>  import org.apache.openjpa.meta.FieldMetaData;
> +import org.apache.openjpa.meta.JavaTypes;
>  import org.apache.openjpa.meta.ValueMetaData;
>  import org.apache.openjpa.util.InternalException;
>  import org.apache.openjpa.util.MetaDataException;
> @@ -406,6 +409,14 @@ public class EmbedFieldStrategy
>             sm.storeObject(field.getIndex(), null);
>             return;
>         }
> +
> +        // handling of lazy embeddables.  if the embedded field is not
> part of any
> +        // fetch group and the result does not contain any embeddable
> columns,
> +        // do not load the embeddable.
> +        if (fetch.requiresFetch(field) == FetchConfiguration.FETCH_NONE &&
> +            !containsEmbeddedResult(fetch, res)) {
> +            return;
> +        }
>
>         //### note: without a null indicator column, the above
> indicatesNull()
>         //### call will always return false, meaning we always have to
> assume
> @@ -426,6 +437,52 @@ public class EmbedFieldStrategy
>         }
>     }
>
> +    /*
> +     * finds an eager fetch field and searches for it in the result.
> +     * if the result does not contain it, assume that it contains no
> embeddable
> +     * column data.  this is a fairly safe assumption given that the
> entire
> +     * embeddable was marked lazy.
> +     */
> +    private boolean containsEmbeddedResult(FetchConfiguration fetch,
> Result res) {
> +        FieldMapping[] fields =
> field.getEmbeddedMapping().getFieldMappings();
> +        for (int i = 0; i < fields.length; i++) {
> +            boolean load = (fetch.requiresFetch(fields[i]) ==
> FetchConfiguration.FETCH_LOAD);
> +            if (load) {
> +                // check the first eager fetch field
> +                return checkResult(fields[i],res);
> +            }
> +        }
> +        // if all fields are lazy and in the default fetch group,
> populate the embeddable
> +        // so its attributes can be loaded when accessed.
> +        return fetch.hasFetchGroup(FetchGroup.NAME_DEFAULT);
> +    }
> +
> +    private boolean checkResult(FieldMapping fm, Result res) {
> +        if (fm.getStrategy() instanceof Joinable) {
> +            Joinable strat = (Joinable)fm.getStrategy();
> +            Column[] cols = strat.getColumns();
> +            for (Column col : cols) {
> +                try {
> +                    if (res.contains(col)) {
> +                        return true;
> +                    }
> +                } catch (Exception e) {
> +                    return false;
> +                }
> +            }
> +        }
> +        // if the field is a collection, also check for an eager result
> which could result from
> +        // a non-lazy relationship in the embeddable
> +        int type = fm.getTypeCode();
> +        if ((type == JavaTypes.ARRAY ||
> +             type == JavaTypes.COLLECTION ||
> +             type == JavaTypes.MAP)
> +            && res.getEager(fm) != null) {
> +            return true;
> +        }
> +        return false;
> +    }
> +
>     private boolean loadFields(OpenJPAStateManager em, JDBCStore store,
>         JDBCFetchConfiguration fetch, Result res)
>         throws SQLException {
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,51 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +import javax.persistence.Basic;
> +import javax.persistence.Column;
> +import javax.persistence.Embeddable;
> +import javax.persistence.FetchType;
> +
> +@Embeddable
> +public class BeverageHolder {
> +
> +    @Basic(fetch=FetchType.LAZY)
> +    @Column(name="BH_DIAMETER")
> +    private int diameter;
> +
> +    @Column(name="BH_DEPTH")
> +    private int depth;
> +
> +    public void setDiameter(int diameter) {
> +        this.diameter = diameter;
> +    }
> +
> +    public int getDiameter() {
> +        return diameter;
> +    }
> +
> +    public void setDepth(int depth) {
> +        this.depth = depth;
> +    }
> +
> +    public int getDepth() {
> +        return depth;
> +    }
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/BeverageHolder.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,63 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +import javax.persistence.Basic;
> +import javax.persistence.Column;
> +import javax.persistence.Embeddable;
> +import javax.persistence.FetchType;
> +
> +@Embeddable
> +public class Guy {
> +
> +    @Basic(fetch=FetchType.LAZY)
> +    @Column(name="GUY_HEIGHT")
> +    private int height;
> +
> +    @Basic(fetch=FetchType.LAZY)
> +    @Column(name="GUY_WEIGHT")
> +    private int weight;
> +
> +    @Column(name="GUY_NAME")
> +    private String name;
> +
> +    public void setName(String name) {
> +        this.name = name;
> +    }
> +
> +    public String getName() {
> +        return name;
> +    }
> +
> +    public void setHeight(int height) {
> +        this.height = height;
> +    }
> +
> +    public int getHeight() {
> +        return height;
> +    }
> +
> +    public void setWeight(int weight) {
> +        this.weight = weight;
> +    }
> +
> +    public int getWeight() {
> +        return weight;
> +    }
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Guy.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,80 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +import javax.persistence.Column;
> +import javax.persistence.Embedded;
> +import javax.persistence.EmbeddedId;
> +import javax.persistence.Entity;
> +import javax.persistence.EnumType;
> +import javax.persistence.Enumerated;
> +import javax.persistence.FetchType;
> +import javax.persistence.Table;
> +
> +import org.apache.openjpa.persistence.Persistent;
> +
> +@Entity
> +@Table(name="REC_TABLE")
> +public class Recliner {
> +
> +    @EmbeddedId
> +    private ReclinerId id;
> +
> +    @Enumerated(EnumType.STRING)
> +    @Column(name="REC_STYLE")
> +    private Style style;
> +
> +    @Embedded  // Lazy fetch set via xml mapping
> +    private Guy guy;
> +
> +    @Persistent(fetch=FetchType.LAZY, embedded=true)
> +    private BeverageHolder holder;
> +
> +    public void setId(ReclinerId id) {
> +        this.id = id;
> +    }
> +
> +    public ReclinerId getId() {
> +        return id;
> +    }
> +
> +    public void setStyle(Style style) {
> +        this.style = style;
> +    }
> +
> +    public Style getStyle() {
> +        return style;
> +    }
> +
> +    public void setGuy(Guy guy) {
> +        this.guy = guy;
> +    }
> +
> +    public Guy getGuy() {
> +        return guy;
> +    }
> +
> +    public void setHolder(BeverageHolder holder) {
> +        this.holder = holder;
> +    }
> +
> +    public BeverageHolder getHolder() {
> +        return holder;
> +    }
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Recliner.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,62 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +import javax.persistence.Column;
> +import javax.persistence.Embeddable;
> +
> +@Embeddable
> +public class ReclinerId {
> +
> +    private int id;
> +    private String color;
> +
> +    public void setId(int id) {
> +        this.id = id;
> +    }
> +
> +    @Column(name="RECID_ID")
> +    public int getId() {
> +        return id;
> +    }
> +
> +    public void setColor(String color) {
> +        this.color = color;
> +    }
> +
> +    @Column(name="RECID_COLOR")
> +    public String getColor() {
> +        return color;
> +    }
> +
> +    @Override
> +    public boolean equals(Object obj) {
> +        if (obj instanceof ReclinerId) {
> +            ReclinerId rid = (ReclinerId)obj;
> +            return rid.id == id &&
> +                rid.color.equals(color);
> +        }
> +        return false;
> +    }
> +
> +    @Override
> +    public int hashCode() {
> +        return id ^ color.hashCode();
> +    }
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/ReclinerId.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,25 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +public enum Style {
> +    WESTERN,
> +    RETRO,
> +    MODERN
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/Style.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,197 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence.embed.lazy;
> +
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Random;
> +
> +import javax.persistence.EntityManager;
> +
> +import org.apache.openjpa.lib.jdbc.AbstractJDBCListener;
> +import org.apache.openjpa.lib.jdbc.JDBCEvent;
> +import org.apache.openjpa.lib.jdbc.JDBCListener;
> +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
> +import org.apache.openjpa.persistence.OpenJPAPersistence;
> +import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
> +
> +public class TestLazyEmbeddable extends AbstractPersistenceTestCase {
> +
> +    protected List<String> _sql = new ArrayList<String>();
> +
> +    /*
> +     * Verifies an entity with annotated (@Persistent) lazy embeddable
> and xml-tagged
> +     * lazy embeddable (openjpa:persistent) with a mix of eager and lazy
> fields are lazily
> +     * loaded (or not) as expected.
> +     */
> +    public void testLazyEmbeddableFields() throws Exception {
> +        _sql.clear();
> +        HashMap<String, Object> props = new HashMap<String, Object>();
> +        props.put("openjpa.jdbc.JDBCListeners",
> +            new JDBCListener[] { new SQLListener() });
> +        OpenJPAEntityManagerFactorySPI emf1 =
> +            (OpenJPAEntityManagerFactorySPI)OpenJPAPersistence.
> +            createEntityManagerFactory("LazyEmbedPU",
> +            "org/apache/openjpa/persistence/embed/lazy/" +
> +            "embed-lazy-persistence.xml", props);
> +
> +        try {
> +            EntityManager em = emf1.createEntityManager();
> +
> +            Recliner rec = new Recliner();
> +            ReclinerId recId = new ReclinerId();
> +            recId.setColor("Camouflage");
> +            recId.setId(new Random().nextInt());
> +            rec.setId(recId);
> +            rec.setStyle(Style.RETRO);
> +
> +            Guy guy = new Guy();
> +            guy.setName("Tom");
> +            guy.setHeight(76);
> +            guy.setWeight(275);
> +            rec.setGuy(guy);
> +
> +            BeverageHolder bh = new BeverageHolder();
> +            bh.setDepth(2);
> +            bh.setDiameter(3);
> +            rec.setHolder(bh);
> +
> +            em.getTransaction().begin();
> +            em.persist(rec);
> +            em.getTransaction().commit();
> +
> +            em.clear();
> +            _sql.clear();
> +
> +            Recliner r2 = em.find(Recliner.class, recId);
> +            assertNotNull("Find returned null object", r2);
> +            assertTrue(selectContains("REC_TABLE", _sql, "REC_STYLE",
> "RECID_ID", "RECID_COLOR"));
> +            assertFalse(selectContains("REC_TABLE", _sql, "GUY_HEIGHT",
> "GUY_WEIGHT", "GUY_NAME",
> +                "BH_DIAMETER", "BH_DEPTH"));
> +            em.detach(r2);
> +            // Lazy embeds should be null after detach.
> +            assertNull("Embedded field guy is null before getter is
> called", r2.getGuy());
> +            assertNull("Embedded field holder is null before getter is
> called", r2.getHolder());
> +
> +            // verify lazy embeds will load on access post-detach and
> merge
> +            r2 = em.merge(r2);
> +            verifyLazyLoading(r2);
> +
> +            em.clear();
> +            _sql.clear();
> +            // verify lazy embeds will load on access after find
> +            r2 = em.find(Recliner.class, recId);
> +            assertNotNull("Find returned null object", r2);
> +            assertTrue(selectContains("REC_TABLE", _sql, "REC_STYLE",
> "RECID_ID", "RECID_COLOR"));
> +            assertFalse(selectContains("REC_TABLE", _sql, "GUY_HEIGHT",
> "GUY_WEIGHT", "GUY_NAME",
> +                "BH_DIAMETER", "BH_DEPTH"));
> +            verifyLazyLoading(r2);
> +        } finally {
> +            cleanupEMF(emf1);
> +        }
> +    }
> +
> +
> +
> +    private void verifyLazyLoading(Recliner r2) {
> +        _sql.clear();
> +        Guy g = r2.getGuy();
> +        assertNotNull("Guy is not null", g);
> +        assertTrue(selectContains("REC_TABLE", _sql, "GUY_NAME"));
> +        assertFalse(selectContains("REC_TABLE", _sql, "GUY_HEIGHT",
> "GUY_WEIGHT"));
> +        _sql.clear();
> +        g.getHeight();
> +        assertTrue(selectContains("REC_TABLE", _sql, "GUY_HEIGHT"));
> +        assertFalse(selectContains("REC_TABLE", _sql, "GUY_NAME",
> "GUY_WEIGHT", "BH_DIAMETER",
> +            "BH_DEPTH"));
> +
> +        _sql.clear();
> +        BeverageHolder holder = r2.getHolder();
> +        assertNotNull("Holder is not null", holder);
> +        assertTrue(selectContains("REC_TABLE", _sql, "BH_DEPTH"));
> +        assertFalse(selectContains("REC_TABLE", _sql, "BH_DIAMETER"));
> +        _sql.clear();
> +        holder.getDiameter();
> +        assertTrue(selectContains("REC_TABLE", _sql, "BH_DIAMETER"));
> +        assertFalse(selectContains("REC_TABLE", _sql, "BH_DEPTH"));
> +    }
> +
> +
> +
> +    private boolean selectContains(String table, List<String> sql,
> String...cols) {
> +        boolean foundSelect = false;
> +        for (String s: sql) {
> +            String stmt = s.toUpperCase();
> +            if (!stmt.startsWith("SELECT") && !stmt.contains(table)) {
> +                continue;
> +            }
> +            foundSelect = true;
> +            for (String col : cols) {
> +                String ucol = col.toUpperCase();
> +                if (!stmt.contains(ucol)) {
> +                   return false;
> +                }
> +            }
> +        }
> +        return foundSelect;
> +    }
> +
> +
> +
> +    private static String toString(List<String> list) {
> +        StringBuffer buf = new StringBuffer();
> +        for (String s : list)
> +            buf.append(s).append("\r\n");
> +        return buf.toString();
> +    }
> +
> +    /**
> +     * Closes a specific entity manager factory and cleans up
> +     * associated tables.
> +     */
> +    private void cleanupEMF(OpenJPAEntityManagerFactorySPI emf1)
> +      throws Exception {
> +
> +        if (emf1 == null)
> +            return;
> +
> +        try {
> +            clear(emf1);
> +        } catch (Exception e) {
> +            // if a test failed, swallow any exceptions that happen
> +            // during tear-down, as these just mask the original problem.
> +            if (testResult.wasSuccessful())
> +                throw e;
> +        } finally {
> +            closeEMF(emf1);
> +        }
> +    }
> +
> +    public class SQLListener
> +        extends AbstractJDBCListener {
> +
> +        @Override
> +        public void beforeExecuteStatement(JDBCEvent event) {
> +            if (event.getSQL() != null && _sql != null) {
> +                _sql.add(event.getSQL());
> +            }
> +        }
> +    }
> +}
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/lazy/TestLazyEmbeddable.java
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,36 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<!--
> + Licensed to the Apache Software Foundation (ASF) under one
> + or more contributor license agreements.  See the NOTICE file
> + distributed with this work for additional information
> + regarding copyright ownership.  The ASF licenses this file
> + to you under the Apache License, Version 2.0 (the
> + "License"); you may not use this file except in compliance
> + with the License.  You may obtain a copy of the License at
> +
> + http://www.apache.org/licenses/LICENSE-2.0
> +
> + Unless required by applicable law or agreed to in writing,
> + software distributed under the License is distributed on an
> + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + KIND, either express or implied.  See the License for the
> + specific language governing permissions and limitations
> + under the License.
> +-->
> +<entity-mappings xmlns="http://www.apache.org/openjpa/ns/orm/extendable"
> +    xmlns:openjpa="http://www.apache.org/openjpa/ns/orm"
> +    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
> +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> +    version="2.0">
> +
> +  <openjpa:openjpa-version version="1.0"/>
> +
> +  <entity class="org.apache.openjpa.persistence.embed.lazy.Recliner">
> +    <attributes>
> +      <openjpa:attributes>
> +        <!-- embeddable should not get fetched along with entity -->
> +        <openjpa:persistent name="guy" fetch="LAZY"/>
> +      </openjpa:attributes>
> +    </attributes>
> +  </entity>
> +</entity-mappings>
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Added:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml?rev=1293250&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml
> (added)
> +++
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml
> Fri Feb 24 13:53:01 2012
> @@ -0,0 +1,33 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!--
> + Licensed to the Apache Software Foundation (ASF) under one
> + or more contributor license agreements.  See the NOTICE file
> + distributed with this work for additional information
> + regarding copyright ownership.  The ASF licenses this file
> + to you under the Apache License, Version 2.0 (the
> + "License"); you may not use this file except in compliance
> + with the License.  You may obtain a copy of the License at
> +
> + http://www.apache.org/licenses/LICENSE-2.0
> +
> + Unless required by applicable law or agreed to in writing,
> + software distributed under the License is distributed on an
> + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + KIND, either express or implied.  See the License for the
> + specific language governing permissions and limitations
> + under the License.
> +-->
> +<persistence xmlns="http://java.sun.com/xml/ns/persistence"
> +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> +    version="2.0">
> +    <persistence-unit name="LazyEmbedPU">
> +
>  <mapping-file>org/apache/openjpa/persistence/embed/lazy/embed-lazy-orm.xml</mapping-file>
> +
>  <class>org.apache.openjpa.persistence.embed.lazy.ReclinerId</class>
> +        <class>org.apache.openjpa.persistence.embed.lazy.Recliner</class>
> +        <class>org.apache.openjpa.persistence.embed.lazy.Guy</class>
> +
>  <class>org.apache.openjpa.persistence.embed.lazy.BeverageHolder</class>
> +        <properties>
> +            <property name="openjpa.jdbc.SynchronizeMappings"
> value="buildSchema"/>
> +        </properties>
> +    </persistence-unit>
> +</persistence>
> \ No newline at end of file
>
> Propchange:
> openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/embed/lazy/embed-lazy-persistence.xml
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Modified:
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=1293250&r1=1293249&r2=1293250&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
> (original)
> +++
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
> Fri Feb 24 13:53:01 2012
> @@ -2542,6 +2542,11 @@ public class XMLPersistenceMetaDataParse
>         parseCommonExtendedAttributes(fmd, attrs);
>         parseTypeAttr(fmd, attrs);
>         // TODO - handle attributes
> +        String val = attrs.getValue("fetch");
> +        if (val != null) {
> +            fmd.setInDefaultFetchGroup("EAGER".equals(val));
> +        }
> +
>         switch (fmd.getDeclaredTypeCode()) {
>         case JavaTypes.ARRAY:
>             if (fmd.getDeclaredType() == byte[].class
>
>
>