mirror of https://github.com/apache/openjpa.git
OPENJPA-316
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@595510 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
634bdc5c92
commit
0071f7b0d8
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.enhance;
|
package org.apache.openjpa.enhance;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -34,6 +35,7 @@ import org.apache.openjpa.lib.log.Log;
|
||||||
import org.apache.openjpa.lib.util.BytecodeWriter;
|
import org.apache.openjpa.lib.util.BytecodeWriter;
|
||||||
import org.apache.openjpa.lib.util.JavaVersions;
|
import org.apache.openjpa.lib.util.JavaVersions;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.lib.util.Files;
|
||||||
import org.apache.openjpa.lib.util.Localizer.Message;
|
import org.apache.openjpa.lib.util.Localizer.Message;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
@ -249,10 +251,14 @@ public class ManagedClassSubclasser {
|
||||||
// but do set the metadata accordingly.
|
// but do set the metadata accordingly.
|
||||||
if (enhancer.isAlreadyRedefined())
|
if (enhancer.isAlreadyRedefined())
|
||||||
ints.add(bc.getType());
|
ints.add(bc.getType());
|
||||||
else if (JavaVersions.VERSION >= 5)
|
else if (JavaVersions.VERSION >= 5) {
|
||||||
map.put(bc.getType(), bc.toByteArray());
|
map.put(bc.getType(), bc.toByteArray());
|
||||||
|
debugBytecodes(bc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!enhancer.isAlreadySubclassed()) {
|
if (!enhancer.isAlreadySubclassed()) {
|
||||||
|
debugBytecodes(bc);
|
||||||
|
|
||||||
// this is the new subclass
|
// this is the new subclass
|
||||||
ClassLoader loader = GeneratedClasses.getMostDerivedLoader(
|
ClassLoader loader = GeneratedClasses.getMostDerivedLoader(
|
||||||
cls, PersistenceCapable.class);
|
cls, PersistenceCapable.class);
|
||||||
|
@ -261,6 +267,22 @@ public class ManagedClassSubclasser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void debugBytecodes(BCClass bc) throws IOException {
|
||||||
|
// Write the bytecodes to disk for debugging purposes.
|
||||||
|
if ("true".equals(System.getProperty(
|
||||||
|
ManagedClassSubclasser.class.getName() + ".dumpBytecodes")))
|
||||||
|
{
|
||||||
|
File tmp = new File(System.getProperty("java.io.tmpdir"));
|
||||||
|
File dir = new File(tmp, "openjpa");
|
||||||
|
dir = new File(dir, "pcsubclasses");
|
||||||
|
dir.mkdirs();
|
||||||
|
dir = Files.getPackageFile(dir, bc.getPackageName(), true);
|
||||||
|
File f = new File(dir, bc.getClassName() + ".class");
|
||||||
|
System.err.println("Writing to " + f);
|
||||||
|
bc.write(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void setIntercepting(OpenJPAConfiguration conf,
|
private static void setIntercepting(OpenJPAConfiguration conf,
|
||||||
ClassLoader envLoader, Class cls) {
|
ClassLoader envLoader, Class cls) {
|
||||||
ClassMetaData meta = conf.getMetaDataRepositoryInstance()
|
ClassMetaData meta = conf.getMetaDataRepositoryInstance()
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.enhance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper methods for dynamically-redefined managed types.
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class DynamicPCHelper {
|
|
||||||
public static boolean isDetached(Object o) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,8 +18,15 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.enhance;
|
package org.apache.openjpa.enhance;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.kernel.StateManagerImpl;
|
import org.apache.openjpa.kernel.StateManagerImpl;
|
||||||
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
import org.apache.openjpa.util.ImplHelper;
|
import org.apache.openjpa.util.ImplHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,4 +192,46 @@ public class RedefinitionHelper {
|
||||||
sm.settingObjectField(pc, idx, cur, next,
|
sm.settingObjectField(pc, idx, cur, next,
|
||||||
OpenJPAStateManager.SET_USER);
|
OpenJPAStateManager.SET_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a container instance that will delegate back to the state
|
||||||
|
* manager to emulate lazy loading. This is used by PC subclasses for
|
||||||
|
* unenhanced types that could not be redefined, and thus do not have
|
||||||
|
* field-interception capabilities. Do this for all collection and
|
||||||
|
* map field types, even if they are in the dfg, in case the fetch
|
||||||
|
* groups are reset at runtime.
|
||||||
|
*
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public static void assignLazyLoadProxies(StateManagerImpl sm) {
|
||||||
|
FieldMetaData[] fmds = sm.getMetaData().getFields();
|
||||||
|
for (int i = 0; i < fmds.length; i++) {
|
||||||
|
switch (fmds[i].getTypeCode()) {
|
||||||
|
case JavaTypes.COLLECTION:
|
||||||
|
case JavaTypes.MAP:
|
||||||
|
PersistenceCapable pc = sm.getPersistenceCapable();
|
||||||
|
Field field = (Field) fmds[i].getBackingMember();
|
||||||
|
Reflection.set(pc, field,
|
||||||
|
newLazyLoadingProxy(fmds[i].getDeclaredType(), i, sm));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object newLazyLoadingProxy(Class type, final int idx,
|
||||||
|
final StateManagerImpl sm) {
|
||||||
|
InvocationHandler handler = new InvocationHandler() {
|
||||||
|
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args)
|
||||||
|
throws Throwable {
|
||||||
|
// this will replace the field in the instance, so the dynamic
|
||||||
|
// proxy should only be called the first time a
|
||||||
|
// lazy-load-proxied field is used in normal usage.
|
||||||
|
Object delegate = sm.fetch(idx);
|
||||||
|
return method.invoke(delegate, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Proxy.newProxyInstance(type.getClassLoader(),
|
||||||
|
new Class[] { type }, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,25 @@ package org.apache.openjpa.kernel;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutput;
|
import java.io.ObjectOutput;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||||
|
import org.apache.openjpa.enhance.DynamicPersistenceCapable;
|
||||||
import org.apache.openjpa.enhance.FieldManager;
|
import org.apache.openjpa.enhance.FieldManager;
|
||||||
|
import org.apache.openjpa.enhance.ManagedInstanceProvider;
|
||||||
import org.apache.openjpa.enhance.PCRegistry;
|
import org.apache.openjpa.enhance.PCRegistry;
|
||||||
import org.apache.openjpa.enhance.PersistenceCapable;
|
import org.apache.openjpa.enhance.PersistenceCapable;
|
||||||
|
import org.apache.openjpa.enhance.RedefinitionHelper;
|
||||||
import org.apache.openjpa.enhance.StateManager;
|
import org.apache.openjpa.enhance.StateManager;
|
||||||
import org.apache.openjpa.enhance.ManagedInstanceProvider;
|
|
||||||
import org.apache.openjpa.enhance.DynamicPersistenceCapable;
|
|
||||||
import org.apache.openjpa.event.LifecycleEvent;
|
import org.apache.openjpa.event.LifecycleEvent;
|
||||||
import org.apache.openjpa.event.LifecycleEventManager;
|
import org.apache.openjpa.event.LifecycleEventManager;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
@ -43,6 +52,7 @@ import org.apache.openjpa.meta.ValueMetaData;
|
||||||
import org.apache.openjpa.meta.ValueStrategies;
|
import org.apache.openjpa.meta.ValueStrategies;
|
||||||
import org.apache.openjpa.util.ApplicationIds;
|
import org.apache.openjpa.util.ApplicationIds;
|
||||||
import org.apache.openjpa.util.Exceptions;
|
import org.apache.openjpa.util.Exceptions;
|
||||||
|
import org.apache.openjpa.util.ImplHelper;
|
||||||
import org.apache.openjpa.util.InternalException;
|
import org.apache.openjpa.util.InternalException;
|
||||||
import org.apache.openjpa.util.InvalidStateException;
|
import org.apache.openjpa.util.InvalidStateException;
|
||||||
import org.apache.openjpa.util.ObjectNotFoundException;
|
import org.apache.openjpa.util.ObjectNotFoundException;
|
||||||
|
@ -50,7 +60,6 @@ import org.apache.openjpa.util.OpenJPAId;
|
||||||
import org.apache.openjpa.util.ProxyManager;
|
import org.apache.openjpa.util.ProxyManager;
|
||||||
import org.apache.openjpa.util.RuntimeExceptionTranslator;
|
import org.apache.openjpa.util.RuntimeExceptionTranslator;
|
||||||
import org.apache.openjpa.util.UserException;
|
import org.apache.openjpa.util.UserException;
|
||||||
import org.apache.openjpa.util.ImplHelper;
|
|
||||||
import serp.util.Numbers;
|
import serp.util.Numbers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,8 +315,11 @@ public class StateManagerImpl
|
||||||
|
|
||||||
// if this is a non-tracking PC, add a hard ref to the appropriate data
|
// if this is a non-tracking PC, add a hard ref to the appropriate data
|
||||||
// sets and give it an opportunity to make a state snapshot.
|
// sets and give it an opportunity to make a state snapshot.
|
||||||
if (!isIntercepting())
|
if (!isIntercepting()) {
|
||||||
saveFields(true);
|
saveFields(true);
|
||||||
|
if (!isNew())
|
||||||
|
RedefinitionHelper.assignLazyLoadProxies(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,6 +327,8 @@ public class StateManagerImpl
|
||||||
* from {@link ClassMetaData#isIntercepting()} in that it checks for
|
* from {@link ClassMetaData#isIntercepting()} in that it checks for
|
||||||
* property access + subclassing in addition to the redefinition /
|
* property access + subclassing in addition to the redefinition /
|
||||||
* enhancement checks.
|
* enhancement checks.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public boolean isIntercepting() {
|
public boolean isIntercepting() {
|
||||||
if (getMetaData().isIntercepting())
|
if (getMetaData().isIntercepting())
|
||||||
|
|
|
@ -398,6 +398,7 @@
|
||||||
<fileset id="enhance.path.ref"
|
<fileset id="enhance.path.ref"
|
||||||
dir="${project.build.testOutputDirectory}">
|
dir="${project.build.testOutputDirectory}">
|
||||||
<include name="**/*.class"/>
|
<include name="**/*.class"/>
|
||||||
|
<exclude name="**/Test*.class"/>
|
||||||
<exclude name="**/inheritance/serializable/*.class"/>
|
<exclude name="**/inheritance/serializable/*.class"/>
|
||||||
<exclude name="**/xml/*.class"/>
|
<exclude name="**/xml/*.class"/>
|
||||||
<exclude name="**/Unenhanced*.class"/>
|
<exclude name="**/Unenhanced*.class"/>
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.enhance;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMTestCase;
|
||||||
|
|
||||||
|
public class TestUnenhancedOneToMany extends SingleEMTestCase {
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
setUp(UnenhancedOne.class, UnenhancedMany.class, CLEAR_TABLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOneToMany() throws Exception {
|
||||||
|
assertFalse(PersistenceCapable.class.isAssignableFrom(
|
||||||
|
UnenhancedOne.class));
|
||||||
|
assertFalse(PersistenceCapable.class.isAssignableFrom(
|
||||||
|
UnenhancedMany.class));
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
UnenhancedOne one = new UnenhancedOne(1000);
|
||||||
|
|
||||||
|
UnenhancedMany manyA = new UnenhancedMany(1);
|
||||||
|
one.getMany().add(manyA);
|
||||||
|
manyA.setOne(one);
|
||||||
|
|
||||||
|
UnenhancedMany manyB = new UnenhancedMany(2);
|
||||||
|
one.getMany().add(manyB);
|
||||||
|
manyB.setOne(one);
|
||||||
|
|
||||||
|
UnenhancedMany manyC = new UnenhancedMany(3);
|
||||||
|
one.getMany().add(manyC);
|
||||||
|
manyC.setOne(one);
|
||||||
|
|
||||||
|
// em should not know about our entities
|
||||||
|
assertFalse(em.contains(one));
|
||||||
|
assertFalse(em.contains(manyA));
|
||||||
|
assertFalse(em.contains(manyB));
|
||||||
|
assertFalse(em.contains(manyC));
|
||||||
|
|
||||||
|
// persist the entity
|
||||||
|
em.persist(one);
|
||||||
|
em.persist(manyA);
|
||||||
|
em.persist(manyB);
|
||||||
|
em.persist(manyC);
|
||||||
|
em.flush();
|
||||||
|
|
||||||
|
// em should now be aware of our entity
|
||||||
|
assertTrue(em.contains(one));
|
||||||
|
assertTrue(em.contains(manyA));
|
||||||
|
assertTrue(em.contains(manyB));
|
||||||
|
assertTrue(em.contains(manyC));
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// recreate entity manager to avoid caching
|
||||||
|
one = null;
|
||||||
|
manyA = null;
|
||||||
|
manyB = null;
|
||||||
|
manyC = null;
|
||||||
|
em.close();
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
// reload one
|
||||||
|
one = em.find(UnenhancedOne.class, 1000);
|
||||||
|
assertNotNull("one is null", one);
|
||||||
|
|
||||||
|
// verify one.getMany(); ensure that it's a dynamic proxy before
|
||||||
|
// it is accessed
|
||||||
|
assertTrue(Proxy.isProxyClass(one.many.getClass()));
|
||||||
|
assertNotNull("one.getMany() is null", one.getMany());
|
||||||
|
Collection<UnenhancedMany> many = one.getMany();
|
||||||
|
assertEquals(3, many.size());
|
||||||
|
|
||||||
|
// reload the many
|
||||||
|
manyA = em.find(UnenhancedMany.class, 1);
|
||||||
|
assertNotNull("manyA is null", manyA);
|
||||||
|
manyB = em.find(UnenhancedMany.class, 2);
|
||||||
|
assertNotNull("manyB is null", manyA);
|
||||||
|
manyC = em.find(UnenhancedMany.class, 3);
|
||||||
|
assertNotNull("manyc is null", manyA);
|
||||||
|
|
||||||
|
// verify many.getOne()
|
||||||
|
assertNotNull("manyA.getOne() is null", manyA.getOne());
|
||||||
|
assertEquals(one, manyA.getOne());
|
||||||
|
assertNotNull("manyB.getOne() is null", manyB.getOne());
|
||||||
|
assertEquals(one, manyB.getOne());
|
||||||
|
assertNotNull("manyC.getOne() is null", manyC.getOne());
|
||||||
|
assertEquals(one, manyC.getOne());
|
||||||
|
|
||||||
|
// verify collection contains each many
|
||||||
|
assertTrue(many.contains(manyA));
|
||||||
|
assertTrue(many.contains(manyB));
|
||||||
|
assertTrue(many.contains(manyC));
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.enhance;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class UnenhancedMany implements Serializable, Cloneable {
|
||||||
|
private static final long serialVersionUID = 4041356744771116705L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private UnenhancedOne one;
|
||||||
|
|
||||||
|
public UnenhancedMany() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnenhancedMany(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnenhancedOne getOne() {
|
||||||
|
return one;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOne(UnenhancedOne one) {
|
||||||
|
this.one = one;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) return true;
|
||||||
|
if (o == null) return false;
|
||||||
|
if (!getClass().isAssignableFrom(o.getClass())) return false;
|
||||||
|
|
||||||
|
return id == ((UnenhancedMany) o).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.enhance;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class UnenhancedOne implements Serializable, Cloneable {
|
||||||
|
private static final long serialVersionUID = -5834998517804641711L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
Collection<UnenhancedMany> many = new HashSet<UnenhancedMany>();
|
||||||
|
|
||||||
|
public UnenhancedOne() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnenhancedOne(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<UnenhancedMany> getMany() {
|
||||||
|
return many;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) return true;
|
||||||
|
if (o == null) return false;
|
||||||
|
if (!getClass().isAssignableFrom(o.getClass())) return false;
|
||||||
|
|
||||||
|
return id == ((UnenhancedOne) o).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue