mirror of https://github.com/apache/openjpa.git
OPENJPA-1175 Updated util methods to handle load state checking of embeddables and collections.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@799425 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b9d609a3b0
commit
9706a82960
|
@ -19,8 +19,12 @@
|
|||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
|
@ -48,4 +52,5 @@ public class EagerEmbed {
|
|||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Embeddable
|
||||
public class EagerEmbedRel {
|
||||
|
||||
@ElementCollection(fetch=FetchType.EAGER)
|
||||
private Set<Integer> intVals;
|
||||
|
||||
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
|
||||
private Set<EagerEntity> eagerEnts;
|
||||
|
||||
public void setIntVals(Set<Integer> intVals) {
|
||||
this.intVals = intVals;
|
||||
}
|
||||
|
||||
public Set<Integer> getIntVals() {
|
||||
return intVals;
|
||||
}
|
||||
|
||||
|
||||
public void setEagerEnts(Set<EagerEntity> eagerEnts) {
|
||||
this.eagerEnts = eagerEnts;
|
||||
}
|
||||
|
||||
public Set<EagerEntity> getEagerEnts() {
|
||||
return eagerEnts;
|
||||
}
|
||||
}
|
|
@ -18,9 +18,13 @@
|
|||
*/
|
||||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
|
@ -36,6 +40,12 @@ public class EagerEntity {
|
|||
@Embedded
|
||||
private EagerEmbed eagerEmbed;
|
||||
|
||||
@Embedded
|
||||
private EagerEmbedRel eagerEmbedRel;
|
||||
|
||||
@ElementCollection(fetch=FetchType.EAGER)
|
||||
private List<EagerEmbed> eagerEmbedColl;
|
||||
|
||||
@Transient
|
||||
private String transField;
|
||||
|
||||
|
@ -70,4 +80,20 @@ public class EagerEntity {
|
|||
public String getTransField() {
|
||||
return transField;
|
||||
}
|
||||
|
||||
public void setEagerEmbedColl(List<EagerEmbed> eagerEmbedColl) {
|
||||
this.eagerEmbedColl = eagerEmbedColl;
|
||||
}
|
||||
|
||||
public List<EagerEmbed> getEagerEmbedColl() {
|
||||
return eagerEmbedColl;
|
||||
}
|
||||
|
||||
public void setEagerEmbedRel(EagerEmbedRel eagerEmbedRel) {
|
||||
this.eagerEmbedRel = eagerEmbedRel;
|
||||
}
|
||||
|
||||
public EagerEmbedRel getEagerEmbedRel() {
|
||||
return eagerEmbedRel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,17 @@
|
|||
*/
|
||||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
|
@ -37,6 +43,15 @@ public class LazyEntity {
|
|||
@Embedded
|
||||
private LazyEmbed lazyEmbed;
|
||||
|
||||
@ElementCollection(fetch=FetchType.LAZY)
|
||||
private List<LazyEmbed> lazyEmbedColl;
|
||||
|
||||
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
|
||||
private List<RelEntity> relEntities;
|
||||
|
||||
@OneToOne(fetch=FetchType.LAZY)
|
||||
private RelEntity relEntity;
|
||||
|
||||
@Transient
|
||||
private String transField;
|
||||
|
||||
|
@ -71,4 +86,28 @@ public class LazyEntity {
|
|||
public String getTransField() {
|
||||
return transField;
|
||||
}
|
||||
|
||||
public void setLazyEmbedColl(List<LazyEmbed> lazyEmbedColl) {
|
||||
this.lazyEmbedColl = lazyEmbedColl;
|
||||
}
|
||||
|
||||
public List<LazyEmbed> getLazyEmbedColl() {
|
||||
return lazyEmbedColl;
|
||||
}
|
||||
|
||||
public void setRelEntities(List<RelEntity> relEntities) {
|
||||
this.relEntities = relEntities;
|
||||
}
|
||||
|
||||
public List<RelEntity> getRelEntities() {
|
||||
return relEntities;
|
||||
}
|
||||
|
||||
public void setRelEntity(RelEntity relEntity) {
|
||||
this.relEntity = relEntity;
|
||||
}
|
||||
|
||||
public RelEntity getRelEntity() {
|
||||
return relEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="MAPENT")
|
||||
public class MapEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@OneToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
|
||||
private MapValEntity mapValEntity;
|
||||
|
||||
@OneToMany(fetch=FetchType.EAGER)
|
||||
private Map<MapKeyEmbed, MapValEntity> mapEntities;
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setMapValEntity(MapValEntity mapValEntity) {
|
||||
this.mapValEntity = mapValEntity;
|
||||
}
|
||||
|
||||
public MapValEntity getMapValEntity() {
|
||||
return mapValEntity;
|
||||
}
|
||||
|
||||
public void setMapEntities(Map<MapKeyEmbed, MapValEntity> mapEntities) {
|
||||
this.mapEntities = mapEntities;
|
||||
}
|
||||
|
||||
public Map<MapKeyEmbed, MapValEntity> getMapEntities() {
|
||||
return mapEntities;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class MapKeyEmbed {
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="MVTABLE")
|
||||
public class MapValEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
private int intVal;
|
||||
|
||||
@OneToOne(fetch=FetchType.EAGER, mappedBy="mapValEntity",
|
||||
cascade=CascadeType.ALL)
|
||||
private MapEntity mapEntity;
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setIntVal(int intVal) {
|
||||
this.intVal = intVal;
|
||||
}
|
||||
|
||||
public int getIntVal() {
|
||||
return intVal;
|
||||
}
|
||||
|
||||
public void setMapEntity(MapEntity mapEntity) {
|
||||
this.mapEntity = mapEntity;
|
||||
}
|
||||
|
||||
public MapEntity getMapEntity() {
|
||||
return mapEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class RelEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
private String name;
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,15 +19,21 @@
|
|||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.persistence.PersistenceUnitUtil;
|
||||
import javax.persistence.PersistenceUtil;
|
||||
import javax.persistence.spi.LoadState;
|
||||
import javax.persistence.spi.PersistenceProvider;
|
||||
import javax.persistence.spi.ProviderUtil;
|
||||
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.OpenJPAPersistence;
|
||||
import org.apache.openjpa.persistence.PersistenceProviderImpl;
|
||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||
|
||||
|
@ -35,7 +41,9 @@ public class TestPersistenceUnitUtil extends SingleEMFTestCase{
|
|||
|
||||
public void setUp() {
|
||||
setUp(CLEAR_TABLES, EagerEntity.class, LazyEmbed.class,
|
||||
LazyEntity.class, EagerEmbed.class);
|
||||
LazyEntity.class, EagerEmbed.class, RelEntity.class,
|
||||
EagerEmbedRel.class, MapEntity.class,
|
||||
MapKeyEmbed.class, MapValEntity.class);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -70,6 +78,85 @@ public class TestPersistenceUnitUtil extends SingleEMFTestCase{
|
|||
verifyIsLoadedEagerState(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the use of PersistenceUnitUtil with multiple PU's.
|
||||
*/
|
||||
public void testMultiplePUs() {
|
||||
OpenJPAEntityManagerFactorySPI emf1 =
|
||||
(OpenJPAEntityManagerFactorySPI)OpenJPAPersistence.
|
||||
createEntityManagerFactory("PUtil1",
|
||||
"org/apache/openjpa/persistence/util/" +
|
||||
"persistence.xml");
|
||||
assertNotNull(emf1);
|
||||
|
||||
OpenJPAEntityManagerFactorySPI emf2 =
|
||||
(OpenJPAEntityManagerFactorySPI)OpenJPAPersistence.
|
||||
createEntityManagerFactory("PUtil2",
|
||||
"org/apache/openjpa/persistence/util/" +
|
||||
"persistence.xml");
|
||||
|
||||
assertNotNull(emf2);
|
||||
assertNotSame(emf, emf1);
|
||||
assertNotSame(emf1, emf2);
|
||||
|
||||
PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
|
||||
PersistenceUnitUtil puu1 = emf1.getPersistenceUnitUtil();
|
||||
PersistenceUnitUtil puu2 = emf2.getPersistenceUnitUtil();
|
||||
|
||||
assertNotSame(puu, puu1);
|
||||
assertNotSame(puu, puu2);
|
||||
assertNotSame(puu1, puu2);
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
EntityManager em1 = emf1.createEntityManager();
|
||||
EntityManager em2 = emf2.createEntityManager();
|
||||
|
||||
verifyPULoadState(em, puu, puu1, puu2);
|
||||
verifyPULoadState(em1, puu1, puu, puu2);
|
||||
verifyPULoadState(em2, puu2, puu, puu1);
|
||||
|
||||
em.close();
|
||||
em1.close();
|
||||
em2.close();
|
||||
|
||||
if (emf1 != null) {
|
||||
emf1.close();
|
||||
}
|
||||
if (emf2 != null) {
|
||||
emf2.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void verifyPULoadState(EntityManager em,
|
||||
PersistenceUnitUtil...puu) {
|
||||
|
||||
EagerEntity ee = createEagerEntity();
|
||||
assertEquals(false, puu[0].isLoaded(ee));
|
||||
assertEquals(false, puu[0].isLoaded(ee,
|
||||
"id"));
|
||||
assertEquals(false, puu[1].isLoaded(ee));
|
||||
assertEquals(false, puu[1].isLoaded(ee,
|
||||
"id"));
|
||||
assertEquals(false, puu[2].isLoaded(ee));
|
||||
assertEquals(false, puu[2].isLoaded(ee,
|
||||
"id"));
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist(ee);
|
||||
em.getTransaction().commit();
|
||||
|
||||
assertEquals(true, puu[0].isLoaded(ee));
|
||||
assertEquals(true, puu[0].isLoaded(ee,
|
||||
"id"));
|
||||
assertEquals(false, puu[1].isLoaded(ee));
|
||||
assertEquals(false, puu[1].isLoaded(ee,
|
||||
"id"));
|
||||
assertEquals(false, puu[2].isLoaded(ee));
|
||||
assertEquals(false, puu[2].isLoaded(ee,
|
||||
"id"));
|
||||
}
|
||||
|
||||
|
||||
private void verifyIsLoadedEagerState(boolean loaded) {
|
||||
PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
|
||||
|
@ -164,6 +251,51 @@ public class TestPersistenceUnitUtil extends SingleEMFTestCase{
|
|||
em.close();
|
||||
}
|
||||
|
||||
public void testPCMapEager() {
|
||||
PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
|
||||
EntityManager em = emf.createEntityManager();
|
||||
|
||||
MapValEntity mve = new MapValEntity();
|
||||
mve.setIntVal(10);
|
||||
MapKeyEmbed mke = new MapKeyEmbed();
|
||||
mke.setFirstName("Jane");
|
||||
mke.setLastName("Doe");
|
||||
|
||||
MapEntity me = new MapEntity();
|
||||
|
||||
assertEquals(false, puu.isLoaded(me));
|
||||
assertEquals(false, puu.isLoaded(me,
|
||||
"mapValEntity"));
|
||||
assertEquals(false, puu.isLoaded(me,
|
||||
"mapEntities"));
|
||||
|
||||
assertEquals(false, puu.isLoaded(mve));
|
||||
|
||||
// Create a circular ref
|
||||
me.setMapValEntity(mve);
|
||||
mve.setMapEntity(me);
|
||||
|
||||
HashMap<MapKeyEmbed, MapValEntity> hm =
|
||||
new HashMap<MapKeyEmbed, MapValEntity>();
|
||||
|
||||
hm.put(mke, mve);
|
||||
me.setMapEntities(hm);
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist(me);
|
||||
em.getTransaction().commit();
|
||||
|
||||
assertEquals(true, puu.isLoaded(me));
|
||||
assertEquals(true, puu.isLoaded(me,
|
||||
"mapValEntity"));
|
||||
assertEquals(true, puu.isLoaded(me,
|
||||
"mapEntities"));
|
||||
|
||||
assertEquals(true, puu.isLoaded(mve));
|
||||
|
||||
em.close();
|
||||
}
|
||||
|
||||
private EagerEntity createEagerEntity() {
|
||||
EagerEntity ee = new EagerEntity();
|
||||
ee.setId(new Random().nextInt());
|
||||
|
@ -188,6 +320,10 @@ public class TestPersistenceUnitUtil extends SingleEMFTestCase{
|
|||
emb.setEndDate(new Date(System.currentTimeMillis()));
|
||||
emb.setStartDate(new Date(System.currentTimeMillis()));
|
||||
le.setLazyEmbed(emb);
|
||||
RelEntity re = new RelEntity();
|
||||
re.setName("My ent");
|
||||
ArrayList<RelEntity> rel = new ArrayList<RelEntity>();
|
||||
rel.add(new RelEntity());
|
||||
return le;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -35,7 +37,8 @@ public class TestPersistenceUtil extends SingleEMFTestCase{
|
|||
|
||||
public void setUp() {
|
||||
setUp(CLEAR_TABLES, EagerEntity.class, LazyEmbed.class,
|
||||
LazyEntity.class, EagerEmbed.class);
|
||||
LazyEntity.class, EagerEmbed.class, EagerEmbedRel.class,
|
||||
RelEntity.class);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -187,6 +190,11 @@ public class TestPersistenceUtil extends SingleEMFTestCase{
|
|||
emb.setEndDate(new Date(System.currentTimeMillis()));
|
||||
emb.setStartDate(new Date(System.currentTimeMillis()));
|
||||
le.setLazyEmbed(emb);
|
||||
RelEntity re = new RelEntity();
|
||||
re.setName("My ent");
|
||||
ArrayList<RelEntity> rel = new ArrayList<RelEntity>();
|
||||
rel.add(new RelEntity());
|
||||
le.setRelEntities(rel);
|
||||
return le;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,12 @@
|
|||
package org.apache.openjpa.persistence.util;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.spi.LoadState;
|
||||
|
@ -33,7 +38,8 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
|
||||
public void setUp() {
|
||||
setUp(CLEAR_TABLES, EagerEntity.class, LazyEmbed.class,
|
||||
LazyEntity.class, EagerEmbed.class);
|
||||
LazyEntity.class, EagerEmbed.class, EagerEmbedRel.class,
|
||||
RelEntity.class);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -72,7 +78,7 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
private void verifyIsLoadedEagerState(LoadState state) {
|
||||
ProviderUtil pu = getProviderUtil();
|
||||
EntityManager em = emf.createEntityManager();
|
||||
EagerEntity ee = createEagerEntity();
|
||||
EagerEntity ee = createEagerEntity(true);
|
||||
|
||||
// Vfy LoadState is unknown for the unmanaged entity
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoaded(ee));
|
||||
|
@ -104,6 +110,10 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
"eagerEmbed"));
|
||||
assertEquals(state, pu.isLoadedWithoutReference(ee,
|
||||
"eagerEmbed"));
|
||||
assertEquals(state, pu.isLoadedWithReference(ee,
|
||||
"eagerEmbedColl"));
|
||||
assertEquals(state, pu.isLoadedWithoutReference(ee,
|
||||
"eagerEmbedColl"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ee,
|
||||
"transField"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ee,
|
||||
|
@ -149,6 +159,11 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
"lazyEmbed"));
|
||||
assertEquals(state, pu.isLoadedWithoutReference(le,
|
||||
"lazyEmbed"));
|
||||
// lazyEmbedColl is lazy fetch so it should not be loaded
|
||||
assertEquals(LoadState.NOT_LOADED, pu.isLoadedWithReference(le,
|
||||
"lazyEmbedColl"));
|
||||
assertEquals(LoadState.NOT_LOADED, pu.isLoadedWithoutReference(le,
|
||||
"lazyEmbedColl"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(le,
|
||||
"transField"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(le,
|
||||
|
@ -164,7 +179,7 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
public void testIsApplicationLoaded() {
|
||||
ProviderUtil pu = getProviderUtil();
|
||||
EntityManager em = emf.createEntityManager();
|
||||
EagerEntity ee = createEagerEntity();
|
||||
EagerEntity ee = createEagerEntity(true);
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist(ee);
|
||||
|
@ -202,15 +217,30 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
"id"));
|
||||
}
|
||||
|
||||
private EagerEntity createEagerEntity() {
|
||||
private EagerEntity createEagerEntity(boolean createRels) {
|
||||
EagerEntity ee = new EagerEntity();
|
||||
ee.setId(new Random().nextInt());
|
||||
ee.setName("EagerEntity");
|
||||
EagerEmbed emb = createEagerEmbed();
|
||||
List<EagerEmbed> embcoll = createEagerEmbedColl();
|
||||
ee.setEagerEmbed(emb);
|
||||
ee.setEagerEmbedColl(embcoll);
|
||||
if (createRels) {
|
||||
EagerEmbedRel eer = createEagerEmbedRel(createRels);
|
||||
ee.setEagerEmbedRel(eer);
|
||||
}
|
||||
ee.setEagerEmbedRel(null);
|
||||
return ee;
|
||||
}
|
||||
|
||||
private List<EagerEmbed> createEagerEmbedColl() {
|
||||
ArrayList<EagerEmbed> al = new ArrayList<EagerEmbed>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
al.add(createEagerEmbed());
|
||||
}
|
||||
return al;
|
||||
}
|
||||
|
||||
private EagerEmbed createEagerEmbed() {
|
||||
EagerEmbed emb = new EagerEmbed();
|
||||
emb.setEndDate(new Date(System.currentTimeMillis()));
|
||||
|
@ -218,15 +248,47 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
return emb;
|
||||
}
|
||||
|
||||
private EagerEmbedRel createEagerEmbedRel(boolean createRels) {
|
||||
EagerEmbedRel emb = new EagerEmbedRel();
|
||||
Set<EagerEntity> ee = new HashSet<EagerEntity>();
|
||||
if (createRels) {
|
||||
ee.add(createEagerEntity(false));
|
||||
ee.add(createEagerEntity(false));
|
||||
ee.add(createEagerEntity(false));
|
||||
}
|
||||
Set<Integer> ints = new HashSet<Integer>();
|
||||
for (int i = 0; i < 12; i++) {
|
||||
ints.add(new Integer(i));
|
||||
}
|
||||
emb.setIntVals(ints);
|
||||
|
||||
emb.setEagerEnts(ee);
|
||||
return emb;
|
||||
}
|
||||
|
||||
private LazyEntity createLazyEntity() {
|
||||
LazyEntity le = new LazyEntity();
|
||||
le.setId(new Random().nextInt());
|
||||
le.setName("LazyEntity");
|
||||
LazyEmbed emb = createLazyEmbed();
|
||||
le.setLazyEmbed(emb);
|
||||
le.setLazyEmbedColl(createLazyEmbedColl());
|
||||
return le;
|
||||
}
|
||||
|
||||
private LazyEmbed createLazyEmbed() {
|
||||
LazyEmbed emb = new LazyEmbed();
|
||||
emb.setEndDate(new Date(System.currentTimeMillis()));
|
||||
emb.setStartDate(new Date(System.currentTimeMillis()));
|
||||
le.setLazyEmbed(emb);
|
||||
return le;
|
||||
return emb;
|
||||
}
|
||||
|
||||
private List<LazyEmbed> createLazyEmbedColl() {
|
||||
ArrayList<LazyEmbed> al = new ArrayList<LazyEmbed>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
al.add(createLazyEmbed());
|
||||
}
|
||||
return al;
|
||||
}
|
||||
|
||||
private void assertEagerLoadState(ProviderUtil pu, Object ent,
|
||||
|
@ -244,6 +306,10 @@ public class TestProviderUtil extends SingleEMFTestCase{
|
|||
"eagerEmbed"));
|
||||
assertEquals(state, pu.isLoadedWithoutReference(ent,
|
||||
"eagerEmbed"));
|
||||
assertEquals(state, pu.isLoadedWithReference(ent,
|
||||
"eagerEmbedRel"));
|
||||
assertEquals(state, pu.isLoadedWithoutReference(ent,
|
||||
"eagerEmbedRel"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ent,
|
||||
"transField"));
|
||||
assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ent,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?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="PUtil1">
|
||||
<class>org.apache.openjpa.persistence.util.EagerEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.LazyEmbed</class>
|
||||
<class>org.apache.openjpa.persistence.util.LazyEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.EagerEmbed</class>
|
||||
<class>org.apache.openjpa.persistence.util.RelEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.EagerEmbedRel</class>
|
||||
<properties>
|
||||
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
|
||||
</properties>
|
||||
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="PUtil2">
|
||||
<class>org.apache.openjpa.persistence.util.EagerEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.LazyEmbed</class>
|
||||
<class>org.apache.openjpa.persistence.util.LazyEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.EagerEmbed</class>
|
||||
<class>org.apache.openjpa.persistence.util.RelEntity</class>
|
||||
<class>org.apache.openjpa.persistence.util.EagerEmbedRel</class>
|
||||
<properties>
|
||||
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
|
@ -20,6 +20,8 @@ package org.apache.openjpa.persistence;
|
|||
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.spi.LoadState;
|
||||
|
||||
|
@ -29,6 +31,9 @@ import org.apache.openjpa.kernel.AbstractBrokerFactory;
|
|||
import org.apache.openjpa.kernel.Broker;
|
||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
import org.apache.openjpa.meta.JavaTypes;
|
||||
import org.apache.openjpa.meta.ValueMetaData;
|
||||
import org.apache.openjpa.util.ImplHelper;
|
||||
|
||||
public class OpenJPAPersistenceUtil {
|
||||
|
||||
|
@ -95,11 +100,16 @@ public class OpenJPAPersistenceUtil {
|
|||
// Cycle through all brokers managed by this factory.
|
||||
Broker[] brokerArr = brokers.toArray(new Broker[brokers.size()]);
|
||||
for (Broker broker : brokerArr) {
|
||||
if (broker != null && !broker.isClosed() &&
|
||||
broker.isPersistent(entity))
|
||||
if (broker != null && !broker.isClosed())
|
||||
if (ImplHelper.isManageable(entity)) {
|
||||
PersistenceCapable pc = (PersistenceCapable)entity;
|
||||
// Vfy this broker is managing the entity
|
||||
if (pc.pcGetGenericContext() == broker) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -146,13 +156,14 @@ public class OpenJPAPersistenceUtil {
|
|||
}
|
||||
StateManager sm = pc.pcGetStateManager();
|
||||
if (sm != null && sm instanceof OpenJPAStateManager) {
|
||||
return isLoaded((OpenJPAStateManager)sm, attr);
|
||||
return isLoaded((OpenJPAStateManager)sm, attr, null);
|
||||
}
|
||||
}
|
||||
return LoadState.UNKNOWN;
|
||||
}
|
||||
|
||||
private static LoadState isLoaded(OpenJPAStateManager sm, String attr) {
|
||||
private static LoadState isLoaded(OpenJPAStateManager sm, String attr,
|
||||
HashSet<OpenJPAStateManager> pcs) {
|
||||
boolean isLoaded = true;
|
||||
BitSet loadSet = sm.getLoaded();
|
||||
if (attr != null) {
|
||||
|
@ -168,15 +179,160 @@ public class OpenJPAPersistenceUtil {
|
|||
}
|
||||
FieldMetaData[] fmds = sm.getMetaData().getFields();
|
||||
// Check load state of all persistent eager fetch attributes
|
||||
if (fmds != null && fmds.length > 0) {
|
||||
pcs = addToLoadSet(pcs, sm);
|
||||
for (FieldMetaData fmd : fmds) {
|
||||
if (fmd.isInDefaultFetchGroup()) {
|
||||
if (!loadSet.get(fmd.getIndex())) {
|
||||
if (!isLoadedField(sm, fmd, pcs)) {
|
||||
isLoaded = false;
|
||||
break;
|
||||
}
|
||||
// TODO: Complete contract for collections
|
||||
}
|
||||
}
|
||||
pcs.remove(sm);
|
||||
}
|
||||
return isLoaded ? LoadState.LOADED : LoadState.NOT_LOADED;
|
||||
}
|
||||
|
||||
private static HashSet<OpenJPAStateManager> addToLoadSet(
|
||||
HashSet<OpenJPAStateManager> pcs, OpenJPAStateManager sm) {
|
||||
if (pcs == null) {
|
||||
pcs = new HashSet<OpenJPAStateManager>();
|
||||
}
|
||||
pcs.add(sm);
|
||||
return pcs;
|
||||
}
|
||||
|
||||
private static boolean isLoadedField(OpenJPAStateManager sm,
|
||||
FieldMetaData fmd, HashSet<OpenJPAStateManager> pcs) {
|
||||
BitSet loadSet = sm.getLoaded();
|
||||
|
||||
// Simple load state check for the field
|
||||
if (!loadSet.get(fmd.getIndex()))
|
||||
return false;
|
||||
|
||||
Object field = sm.fetchField(fmd.getIndex(), false);
|
||||
|
||||
// Get the state manager for the field, if it is a PC
|
||||
OpenJPAStateManager ofsm = getStateManager(field);
|
||||
|
||||
// Prevent circular load state evaluation for this sm.
|
||||
if (ofsm != null && pcs.contains(ofsm))
|
||||
return true;
|
||||
|
||||
// If a collection type, determine if it is loaded
|
||||
switch (fmd.getDeclaredTypeCode()) {
|
||||
case JavaTypes.COLLECTION:
|
||||
return isLoadedCollection(sm, fmd.getElement(),
|
||||
(Collection<?>)field, pcs);
|
||||
case JavaTypes.MAP:
|
||||
return isLoadedMap(sm, fmd,
|
||||
(Map<?,?>)field, pcs);
|
||||
case JavaTypes.ARRAY:
|
||||
return isLoadedArray(sm, fmd.getElement(),
|
||||
(Object[])field, pcs);
|
||||
}
|
||||
// If other PC type, determine if it is loaded
|
||||
if (ofsm != null && fmd.isDeclaredTypePC()) {
|
||||
return isLoaded(ofsm, null, pcs) ==
|
||||
LoadState.LOADED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isLoadedCollection(OpenJPAStateManager sm,
|
||||
ValueMetaData vmd, Collection<?> coll, HashSet<OpenJPAStateManager> pcs) {
|
||||
|
||||
// This field passed the load state check in isLoadedField, so
|
||||
// if any of these conditions are true the collection is loaded.
|
||||
if (sm == null || coll == null || coll.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert to array to prevent concurrency issues
|
||||
Object[] arr = coll.toArray();
|
||||
|
||||
return isLoadedArray(sm, vmd, arr, pcs);
|
||||
}
|
||||
|
||||
private static boolean isLoadedArray(OpenJPAStateManager sm,
|
||||
ValueMetaData vmd, Object[] arr,
|
||||
HashSet<OpenJPAStateManager> pcs) {
|
||||
|
||||
// This field passed the load state check in isLoadedField, so
|
||||
// if any of these conditions are true the array is loaded.
|
||||
if (sm == null || arr == null || arr.length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not a collection of PC's
|
||||
if (!vmd.isDeclaredTypePC()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Object pc : arr) {
|
||||
OpenJPAStateManager esm = getStateManager(pc);
|
||||
if (esm == null) {
|
||||
return true;
|
||||
}
|
||||
if (!(isLoaded(esm, null, pcs) == LoadState.LOADED))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isLoadedMap(OpenJPAStateManager sm,
|
||||
FieldMetaData fmd, Map<?,?> map, HashSet<OpenJPAStateManager> pcs) {
|
||||
|
||||
// This field passed the load state check in isLoadedField, so
|
||||
// if any of these conditions are true the map is loaded.
|
||||
if (sm == null || map == null || map.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean keyIsPC = fmd.getKey().isDeclaredTypePC();
|
||||
boolean valIsPC = fmd.getElement().isDeclaredTypePC();
|
||||
|
||||
// Map is does not contain PCs in either keys or values
|
||||
if (!(keyIsPC || valIsPC)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Object[] arr = map.keySet().toArray();
|
||||
|
||||
for (Object key : arr) {
|
||||
if (keyIsPC) {
|
||||
OpenJPAStateManager ksm = getStateManager(key);
|
||||
if (ksm == null) {
|
||||
return true;
|
||||
}
|
||||
if (!(isLoaded(ksm, null, pcs) == LoadState.LOADED))
|
||||
return false;
|
||||
}
|
||||
if (valIsPC) {
|
||||
Object value = map.get(key);
|
||||
OpenJPAStateManager vsm = getStateManager(value);
|
||||
if (vsm == null) {
|
||||
return true;
|
||||
}
|
||||
if (!(isLoaded(vsm, null, pcs) == LoadState.LOADED))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static OpenJPAStateManager getStateManager(Object obj) {
|
||||
if (obj == null || !(obj instanceof PersistenceCapable)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PersistenceCapable pc = (PersistenceCapable)obj;
|
||||
StateManager sm = pc.pcGetStateManager();
|
||||
if (sm == null || !(sm instanceof OpenJPAStateManager)) {
|
||||
return null;
|
||||
}
|
||||
return (OpenJPAStateManager)sm;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,4 +427,44 @@ an obvious reason to create and close multiple <classname>EntityManagerFactory
|
|||
IllegalStateException</classname>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="jpa_overview_emfactory_puutil">
|
||||
<title>
|
||||
PersistenceUnitUtil
|
||||
</title>
|
||||
<indexterm zone="jpa_overview_emfactory_puutil">
|
||||
<primary>
|
||||
EntityManagerFactory
|
||||
</primary>
|
||||
<secondary>
|
||||
util
|
||||
</secondary>
|
||||
</indexterm>
|
||||
<programlisting>
|
||||
public PersistenceUnitUtil getPersistenceUnitUtil();
|
||||
</programlisting>
|
||||
<para>
|
||||
The <classname>EntityManagerFactory</classname> method
|
||||
<methodname>getPersistenceUnitUtil</methodname> to provide access to a
|
||||
<classname>PersistenceUnitUtil</classname> utility. <classname>PersistenceUnitUtil</classname>
|
||||
can be used to obtain the identity of a managed object and determine the load
|
||||
state of the entity or one of its attributes. If the object is not
|
||||
managed by one of the entity managers created from the entity manager factory
|
||||
from which the utility was obtained, the <methodname>getIdentifier</methodname> method will
|
||||
return null and the <methodname>isLoaded</methodname> methods will return false.
|
||||
<programlisting>
|
||||
EntityManagerFactory emf = Persistence.createEntityManagerFactory();
|
||||
PersistenceUnitUtil puUtil = emf.getPersistenceUnitUtil();
|
||||
|
||||
if (puUtil.getIdentifier(deptEntity) == null) {
|
||||
throw new Exception("Identity is not valid.");
|
||||
}
|
||||
if (!puUtil.isLoaded(deptEntity, "employees")) {
|
||||
throw new Exception("Employees not loaded.")
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -75,6 +75,7 @@ EntityManagerFactory</classname> objects in a vendor-neutral fashion.
|
|||
<programlisting>
|
||||
public static EntityManagerFactory createEntityManagerFactory(String name);
|
||||
public static EntityManagerFactory createEntityManagerFactory(String name, Map props);
|
||||
public static PersistenceUtil getPersistenceUtil();
|
||||
</programlisting>
|
||||
<para>
|
||||
Each <methodname>createEntityManagerFactory</methodname> method searches the
|
||||
|
@ -93,6 +94,18 @@ the <filename>conf</filename> directory, you could place an <classname>
|
|||
EntityManagerFactory</classname> definition in <filename>
|
||||
conf/META-INF/persistence.xml</filename>.
|
||||
</para>
|
||||
<para>
|
||||
The <methodname>getPersistenceUtil</methodname> method returns a PersistenceUtil
|
||||
interface that can be used to determine whether an entity or attribute of an
|
||||
entity is loaded.
|
||||
</para>
|
||||
<programlisting>
|
||||
PersistenceUtil pUtil = Persistence.getPersistenceUtil();
|
||||
|
||||
if (!pUtil.isLoaded(myEntity)) {
|
||||
loadEntity(myEntity);
|
||||
}
|
||||
</programlisting>
|
||||
<section id="jpa_overview_persistence_xml">
|
||||
<title>
|
||||
persistence.xml
|
||||
|
|
Loading…
Reference in New Issue