mirror of https://github.com/apache/openjpa.git
OPENJPA-147 -- managed interface support. Also includes failure test case for OPENJPA-481.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@610924 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2933147f53
commit
d4a2929a57
|
@ -176,7 +176,9 @@ public class PCEnhancer {
|
||||||
private boolean _bcsConfigured = false;
|
private boolean _bcsConfigured = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Supply configuration and type to enhance.
|
* Constructor. Supply configuration and type to enhance. This will look
|
||||||
|
* up the metadata for <code>type</code> from <code>conf</code>'s
|
||||||
|
* repository.
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, Class type) {
|
public PCEnhancer(OpenJPAConfiguration conf, Class type) {
|
||||||
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
|
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
|
||||||
|
@ -185,12 +187,14 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Supply configuration and type to enhance.
|
* Constructor. Supply configuration and type to enhance. This will look
|
||||||
|
* up the metadata for <code>meta</code> by converting back to a class
|
||||||
|
* and then loading from <code>conf</code>'s repository.
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData type) {
|
public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) {
|
||||||
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
|
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
|
||||||
.loadProjectClassAction(new Project(), type.getDescribedType())),
|
.loadProjectClassAction(new Project(), meta.getDescribedType())),
|
||||||
type.getRepository());
|
meta.getRepository());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,6 +245,36 @@ public class PCEnhancer {
|
||||||
_meta = _repos.getMetaData(type.getType(), loader, false);
|
_meta = _repos.getMetaData(type.getType(), loader, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. Supply repository. The repository's configuration will
|
||||||
|
* be used, and the metadata passed in will be used as-is without doing
|
||||||
|
* any additional lookups. This is useful when running the enhancer
|
||||||
|
* during metadata load.
|
||||||
|
*
|
||||||
|
* @param repos a metadata repository to use for metadata access,
|
||||||
|
* or null to create a new reporitory; the repository
|
||||||
|
* from the given configuration isn't used by default
|
||||||
|
* because the configuration might be an
|
||||||
|
* implementation-specific subclass whose metadata
|
||||||
|
* required more than just base metadata files
|
||||||
|
* @param type the bytecode representation fo the type to
|
||||||
|
* enhance; this can be created from any stream or file
|
||||||
|
* @param meta the metadata to use for processing this type.
|
||||||
|
*
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public PCEnhancer(MetaDataRepository repos, BCClass type,
|
||||||
|
ClassMetaData meta) {
|
||||||
|
_managedType = type;
|
||||||
|
_pc = type;
|
||||||
|
|
||||||
|
_log = repos.getConfiguration()
|
||||||
|
.getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
||||||
|
|
||||||
|
_repos = repos;
|
||||||
|
_meta = meta;
|
||||||
|
}
|
||||||
|
|
||||||
static String toPCSubclassName(Class cls) {
|
static String toPCSubclassName(Class cls) {
|
||||||
return Strings.getPackageName(PCEnhancer.class) + "."
|
return Strings.getPackageName(PCEnhancer.class) + "."
|
||||||
+ cls.getName().replace('.', '$') + "$pcsubclass";
|
+ cls.getName().replace('.', '$') + "$pcsubclass";
|
||||||
|
@ -453,7 +487,7 @@ public class PCEnhancer {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// if managed interface, skip
|
// if managed interface, skip
|
||||||
if (_managedType.isInterface())
|
if (_pc.isInterface())
|
||||||
return ENHANCE_INTERFACE;
|
return ENHANCE_INTERFACE;
|
||||||
|
|
||||||
// check if already enhanced
|
// check if already enhanced
|
||||||
|
@ -526,8 +560,6 @@ public class PCEnhancer {
|
||||||
} else {
|
} else {
|
||||||
_isAlreadySubclassed = true;
|
_isAlreadySubclassed = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_pc = _managedType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bcsConfigured = true;
|
_bcsConfigured = true;
|
||||||
|
@ -2656,8 +2688,10 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pcPCSuperclass = <superClass>;
|
// pcPCSuperclass = <superClass>;
|
||||||
code.classconstant().setClass(getType(_meta.
|
// this intentionally calls getDescribedType() directly
|
||||||
getPCSuperclassMetaData()));
|
// instead of PCEnhancer.getType()
|
||||||
|
code.classconstant().setClass(
|
||||||
|
_meta.getPCSuperclassMetaData().getDescribedType());
|
||||||
code.putstatic().setField(SUPER, Class.class);
|
code.putstatic().setField(SUPER, Class.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2698,7 +2732,7 @@ public class PCEnhancer {
|
||||||
// PCRegistry.register (cls,
|
// PCRegistry.register (cls,
|
||||||
// pcFieldNames, pcFieldTypes, pcFieldFlags,
|
// pcFieldNames, pcFieldTypes, pcFieldFlags,
|
||||||
// pcPCSuperclass, alias, new XXX ());
|
// pcPCSuperclass, alias, new XXX ());
|
||||||
code.classconstant().setClass(_managedType);
|
code.classconstant().setClass(_meta.getDescribedType());
|
||||||
code.getstatic().setField(PRE + "FieldNames", String[].class);
|
code.getstatic().setField(PRE + "FieldNames", String[].class);
|
||||||
code.getstatic().setField(PRE + "FieldTypes", Class[].class);
|
code.getstatic().setField(PRE + "FieldTypes", Class[].class);
|
||||||
code.getstatic().setField(PRE + "FieldFlags", byte[].class);
|
code.getstatic().setField(PRE + "FieldFlags", byte[].class);
|
||||||
|
@ -3627,19 +3661,19 @@ public class PCEnhancer {
|
||||||
// first, see if we can convert the attribute name to a field name
|
// first, see if we can convert the attribute name to a field name
|
||||||
String fieldName = toBackingFieldName(attrName);
|
String fieldName = toBackingFieldName(attrName);
|
||||||
|
|
||||||
// next, find the field in the managed type.
|
// next, find the field in the managed type hierarchy
|
||||||
BCField[] fields = (BCField[]) AccessController
|
|
||||||
.doPrivileged(J2DoPrivHelper.getBCClassFieldsAction(_managedType,
|
|
||||||
fieldName));
|
|
||||||
BCField field = null;
|
BCField field = null;
|
||||||
for (int i = 0; i < fields.length; i++) {
|
outer: for (BCClass bc = _pc; bc != null; bc = bc.getSuperclassBC()) {
|
||||||
field = fields[i];
|
BCField[] fields = (BCField[]) AccessController
|
||||||
// if we reach a field declared in this type, then this is the
|
.doPrivileged(J2DoPrivHelper.getBCClassFieldsAction(bc,
|
||||||
// most-masking field, and is the one that we want.
|
fieldName));
|
||||||
// ##### probably should walk up the hierarchy, or check that
|
for (int i = 0; i < fields.length; i++) {
|
||||||
// ##### serp does that.
|
field = fields[i];
|
||||||
if (fields[i].getDeclarer() == declarer) {
|
// if we reach a field declared in this type, then this is the
|
||||||
break;
|
// most-masking field, and is the one that we want.
|
||||||
|
if (fields[i].getDeclarer() == declarer) {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.openjpa.lib.util.Localizer;
|
||||||
import org.apache.openjpa.lib.util.ReferenceMap;
|
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||||
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||||
import org.apache.openjpa.util.UserException;
|
import org.apache.openjpa.util.UserException;
|
||||||
|
import org.apache.openjpa.util.InvalidStateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks registered persistence-capable classes.
|
* Tracks registered persistence-capable classes.
|
||||||
|
|
|
@ -557,7 +557,11 @@ public interface Broker
|
||||||
* an interface or an abstract class whose abstract methods follow the
|
* an interface or an abstract class whose abstract methods follow the
|
||||||
* JavaBeans convention, this method will create a concrete implementation
|
* JavaBeans convention, this method will create a concrete implementation
|
||||||
* according to the metadata that defines the class.
|
* according to the metadata that defines the class.
|
||||||
* Otherwise, this will return an instance of the specified class.
|
* Otherwise, if <code>cls</code> is a managed type, this will return an
|
||||||
|
* instance of the specified class.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if <code>cls</code> is not a managed
|
||||||
|
* type or interface.
|
||||||
*/
|
*/
|
||||||
public Object newInstance(Class cls);
|
public Object newInstance(Class cls);
|
||||||
|
|
||||||
|
|
|
@ -2641,8 +2641,6 @@ public class BrokerImpl
|
||||||
PersistenceCapable copy;
|
PersistenceCapable copy;
|
||||||
PCState state;
|
PCState state;
|
||||||
Class type = meta.getDescribedType();
|
Class type = meta.getDescribedType();
|
||||||
if (type.isInterface())
|
|
||||||
type = meta.getInterfaceImpl();
|
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
// give copy and the original instance the same state manager
|
// give copy and the original instance the same state manager
|
||||||
// so that we can copy fields from one to the other
|
// so that we can copy fields from one to the other
|
||||||
|
@ -4152,11 +4150,7 @@ public class BrokerImpl
|
||||||
public Object newInstance(Class cls) {
|
public Object newInstance(Class cls) {
|
||||||
assertOpen();
|
assertOpen();
|
||||||
|
|
||||||
if (cls.isInterface()) {
|
if (!cls.isInterface() && Modifier.isAbstract(cls.getModifiers()))
|
||||||
ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
|
|
||||||
getMetaData(cls, _loader, true);
|
|
||||||
cls = meta.getInterfaceImpl();
|
|
||||||
} else if (Modifier.isAbstract(cls.getModifiers()))
|
|
||||||
throw new UnsupportedOperationException(_loc.get
|
throw new UnsupportedOperationException(_loc.get
|
||||||
("new-abstract", cls).getMessage());
|
("new-abstract", cls).getMessage());
|
||||||
|
|
||||||
|
@ -4169,7 +4163,14 @@ public class BrokerImpl
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PCRegistry.newInstance(cls, null, false);
|
try {
|
||||||
|
return PCRegistry.newInstance(cls, null, false);
|
||||||
|
} catch (IllegalStateException ise) {
|
||||||
|
IllegalArgumentException iae =
|
||||||
|
new IllegalArgumentException(ise.getMessage());
|
||||||
|
iae.setStackTrace(ise.getStackTrace());
|
||||||
|
throw iae;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getObjectId(Object obj) {
|
public Object getObjectId(Object obj) {
|
||||||
|
|
|
@ -260,8 +260,6 @@ public class StateManagerImpl
|
||||||
}
|
}
|
||||||
_meta = sub;
|
_meta = sub;
|
||||||
}
|
}
|
||||||
if (cls.isInterface())
|
|
||||||
cls = _meta.getInterfaceImpl();
|
|
||||||
|
|
||||||
PersistenceCapable inst = PCRegistry.newInstance(cls, this, _oid, true);
|
PersistenceCapable inst = PCRegistry.newInstance(cls, this, _oid, true);
|
||||||
if (inst == null) {
|
if (inst == null) {
|
||||||
|
@ -814,7 +812,8 @@ public class StateManagerImpl
|
||||||
|
|
||||||
SaveFieldManager saved = getSaveFieldManager();
|
SaveFieldManager saved = getSaveFieldManager();
|
||||||
if (saved == null)
|
if (saved == null)
|
||||||
throw new InternalException(_loc.get("no-saved-fields"));
|
throw new InternalException(_loc.get("no-saved-fields",
|
||||||
|
getMetaData().getDescribedType().getName()));
|
||||||
|
|
||||||
FieldMetaData[] fmds = getMetaData().getFields();
|
FieldMetaData[] fmds = getMetaData().getFields();
|
||||||
for (int i = 0; i < fmds.length; i++) {
|
for (int i = 0; i < fmds.length; i++) {
|
||||||
|
|
|
@ -180,6 +180,8 @@ public abstract class AbstractMetaDataDefaults
|
||||||
*/
|
*/
|
||||||
private boolean populateFromPCRegistry(ClassMetaData meta) {
|
private boolean populateFromPCRegistry(ClassMetaData meta) {
|
||||||
Class cls = meta.getDescribedType();
|
Class cls = meta.getDescribedType();
|
||||||
|
if (!PCRegistry.isRegistered(cls))
|
||||||
|
return false;
|
||||||
try {
|
try {
|
||||||
String[] fieldNames = PCRegistry.getFieldNames(cls);
|
String[] fieldNames = PCRegistry.getFieldNames(cls);
|
||||||
Class[] fieldTypes = PCRegistry.getFieldTypes(cls);
|
Class[] fieldTypes = PCRegistry.getFieldTypes(cls);
|
||||||
|
@ -198,9 +200,6 @@ public abstract class AbstractMetaDataDefaults
|
||||||
populate(fmd);
|
populate(fmd);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (IllegalStateException iae) {
|
|
||||||
// thrown by registry when no metadata available
|
|
||||||
return false;
|
|
||||||
} catch (OpenJPAException ke) {
|
} catch (OpenJPAException ke) {
|
||||||
throw ke;
|
throw ke;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -732,6 +732,11 @@ public class ClassMetaData
|
||||||
if (!_type.isInterface())
|
if (!_type.isInterface())
|
||||||
throw new MetaDataException(_loc.get("not-interface", _type));
|
throw new MetaDataException(_loc.get("not-interface", _type));
|
||||||
_interface = managedInterface ? Boolean.TRUE : Boolean.FALSE;
|
_interface = managedInterface ? Boolean.TRUE : Boolean.FALSE;
|
||||||
|
|
||||||
|
// managed interfaces always do proper interception; OpenJPA generates
|
||||||
|
// the implementations.
|
||||||
|
if (isManagedInterface())
|
||||||
|
setIntercepting(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2235,6 +2240,7 @@ public class ClassMetaData
|
||||||
_extent = (meta.getRequiresExtent()) ? Boolean.TRUE : Boolean.FALSE;
|
_extent = (meta.getRequiresExtent()) ? Boolean.TRUE : Boolean.FALSE;
|
||||||
_embedded = (meta.isEmbeddedOnly()) ? Boolean.TRUE : Boolean.FALSE;
|
_embedded = (meta.isEmbeddedOnly()) ? Boolean.TRUE : Boolean.FALSE;
|
||||||
_interface = (meta.isManagedInterface()) ? Boolean.TRUE : Boolean.FALSE;
|
_interface = (meta.isManagedInterface()) ? Boolean.TRUE : Boolean.FALSE;
|
||||||
|
setIntercepting(meta.isIntercepting());
|
||||||
_impl = meta.getInterfaceImpl();
|
_impl = meta.getInterfaceImpl();
|
||||||
_identity = meta.getIdentityType();
|
_identity = meta.getIdentityType();
|
||||||
_idStrategy = meta.getIdentityStrategy();
|
_idStrategy = meta.getIdentityStrategy();
|
||||||
|
|
|
@ -114,14 +114,13 @@ class InterfaceImplGenerator {
|
||||||
// copy the BCClass into the enhancer project.
|
// copy the BCClass into the enhancer project.
|
||||||
bc = _enhProject.loadClass(new ByteArrayInputStream(bc.toByteArray()),
|
bc = _enhProject.loadClass(new ByteArrayInputStream(bc.toByteArray()),
|
||||||
loader);
|
loader);
|
||||||
PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(), bc,
|
PCEnhancer enhancer = new PCEnhancer(_repos, bc, meta);
|
||||||
meta);
|
|
||||||
|
|
||||||
int result = enhancer.run();
|
int result = enhancer.run();
|
||||||
if (result != PCEnhancer.ENHANCE_PC)
|
if (result != PCEnhancer.ENHANCE_PC)
|
||||||
throw new InternalException(_loc.get("interface-badenhance",
|
throw new InternalException(_loc.get("interface-badenhance",
|
||||||
iface)).setFatal(true);
|
iface)).setFatal(true);
|
||||||
try{
|
try {
|
||||||
// load the class for real.
|
// load the class for real.
|
||||||
impl = Class.forName(bc.getName(), true, enhLoader);
|
impl = Class.forName(bc.getName(), true, enhLoader);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -229,4 +228,18 @@ class InterfaceImplGenerator {
|
||||||
} catch (PrivilegedActionException pae) {}
|
} catch (PrivilegedActionException pae) {}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isImplType(Class cls) {
|
||||||
|
return (cls.getName().endsWith(POSTFIX)
|
||||||
|
&& cls.getName().indexOf('$') != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class toManagedInterface(Class cls) {
|
||||||
|
Class[] ifaces = cls.getInterfaces();
|
||||||
|
for (int i = 0; i < ifaces.length; i++) {
|
||||||
|
if (_impls.get(ifaces[i]) == cls)
|
||||||
|
return ifaces[i];
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(cls.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,11 @@ public class MetaDataRepository
|
||||||
DynamicPersistenceCapable.class.isAssignableFrom(cls))
|
DynamicPersistenceCapable.class.isAssignableFrom(cls))
|
||||||
cls = cls.getSuperclass();
|
cls = cls.getSuperclass();
|
||||||
|
|
||||||
|
// if cls is a generated interface, use the user interface
|
||||||
|
// to locate metadata
|
||||||
|
if (cls != null && _implGen.isImplType(cls))
|
||||||
|
cls = _implGen.toManagedInterface(cls);
|
||||||
|
|
||||||
ClassMetaData meta = getMetaDataInternal(cls, envLoader);
|
ClassMetaData meta = getMetaDataInternal(cls, envLoader);
|
||||||
if (meta == null && mustExist) {
|
if (meta == null && mustExist) {
|
||||||
if (cls != null &&
|
if (cls != null &&
|
||||||
|
@ -952,7 +957,6 @@ public class MetaDataRepository
|
||||||
throw new MetaDataException(_loc.get("not-managed-interface",
|
throw new MetaDataException(_loc.get("not-managed-interface",
|
||||||
meta, impl));
|
meta, impl));
|
||||||
_ifaces.put(meta.getDescribedType(), impl);
|
_ifaces.put(meta.getDescribedType(), impl);
|
||||||
_metas.put(impl, meta);
|
|
||||||
addDeclaredInterfaceImpl(meta, meta.getDescribedType());
|
addDeclaredInterfaceImpl(meta, meta.getDescribedType());
|
||||||
ClassMetaData sup = meta.getPCSuperclassMetaData();
|
ClassMetaData sup = meta.getPCSuperclassMetaData();
|
||||||
while (sup != null) {
|
while (sup != null) {
|
||||||
|
@ -964,9 +968,7 @@ public class MetaDataRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized InterfaceImplGenerator getImplGenerator() {
|
InterfaceImplGenerator getImplGenerator() {
|
||||||
if (_implGen == null)
|
|
||||||
_implGen = new InterfaceImplGenerator(this);
|
|
||||||
return _implGen;
|
return _implGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,6 +1280,11 @@ public class MetaDataRepository
|
||||||
cls = classForName((String) itr.next(), clsLoader);
|
cls = classForName((String) itr.next(), clsLoader);
|
||||||
if (cls != null)
|
if (cls != null)
|
||||||
classes.add(cls);
|
classes.add(cls);
|
||||||
|
|
||||||
|
// if the class is an interface, load its metadata to kick
|
||||||
|
// off the impl generator
|
||||||
|
if (cls.isInterface())
|
||||||
|
getMetaData(cls, clsLoader, false);
|
||||||
}
|
}
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
@ -1548,6 +1555,8 @@ public class MetaDataRepository
|
||||||
|
|
||||||
public void endConfiguration() {
|
public void endConfiguration() {
|
||||||
initializeMetaDataFactory();
|
initializeMetaDataFactory();
|
||||||
|
if (_implGen == null)
|
||||||
|
_implGen = new InterfaceImplGenerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeMetaDataFactory() {
|
private void initializeMetaDataFactory() {
|
||||||
|
|
|
@ -301,9 +301,7 @@ public class ApplicationIds {
|
||||||
// oid instance
|
// oid instance
|
||||||
if (!Modifier.isAbstract(meta.getDescribedType().getModifiers())
|
if (!Modifier.isAbstract(meta.getDescribedType().getModifiers())
|
||||||
&& !hasPCPrimaryKeyFields(meta)) {
|
&& !hasPCPrimaryKeyFields(meta)) {
|
||||||
Class type = meta.getInterfaceImpl();
|
Class type = meta.getDescribedType();
|
||||||
if (type == null)
|
|
||||||
type = meta.getDescribedType();
|
|
||||||
PersistenceCapable pc = PCRegistry.newInstance(type, null, oid,
|
PersistenceCapable pc = PCRegistry.newInstance(type, null, oid,
|
||||||
false);
|
false);
|
||||||
Object copy = pc.pcNewObjectIdInstance();
|
Object copy = pc.pcNewObjectIdInstance();
|
||||||
|
|
|
@ -388,11 +388,11 @@ multi-threaded-access: Multiple concurrent threads attempted to access a \
|
||||||
single broker. By default brokers are not thread safe; if you require \
|
single broker. By default brokers are not thread safe; if you require \
|
||||||
and/or intend a broker to be accessed by more than one thread, set the \
|
and/or intend a broker to be accessed by more than one thread, set the \
|
||||||
openjpa.Multithreaded property to true to override the default behavior.
|
openjpa.Multithreaded property to true to override the default behavior.
|
||||||
no-saved-fields: No state snapshot is available for "{0}", but this instance \
|
no-saved-fields: No state snapshot is available for instance of type "{0}", \
|
||||||
uses state-comparison for dirty detection.
|
but this instance uses state-comparison for dirty detection.
|
||||||
cant-serialize-flushed-broker: Serialization not allowed once a broker has \
|
cant-serialize-flushed-broker: Serialization not allowed once a broker has \
|
||||||
been flushed.
|
been flushed.
|
||||||
cant-serialize-pessimistic-broker: Serialization not allowed for brokers with \
|
cant-serialize-pessimistic-broker: Serialization not allowed for brokers with \
|
||||||
an active datastore (pessimistic) transaction.
|
an active datastore (pessimistic) transaction.
|
||||||
cant-serialize-connected-broker: Serialization not allowed for brokers with \
|
cant-serialize-connected-broker: Serialization not allowed for brokers with \
|
||||||
an active connection to the database.
|
an active connection to the database.
|
||||||
|
|
|
@ -40,6 +40,9 @@ public class EmbedValue {
|
||||||
@JoinColumn(name = "EMB_REL")
|
@JoinColumn(name = "EMB_REL")
|
||||||
protected EmbedOwner owner;
|
protected EmbedOwner owner;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private int transientField;
|
||||||
|
|
||||||
public void setBasic(String basic) {
|
public void setBasic(String basic) {
|
||||||
this.basic = basic;
|
this.basic = basic;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedClobFieldStrategy;
|
||||||
import org.apache.openjpa.jdbc.meta.strats.StringFieldStrategy;
|
import org.apache.openjpa.jdbc.meta.strats.StringFieldStrategy;
|
||||||
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
import org.apache.openjpa.persistence.JPAFacadeHelper;
|
||||||
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for embedded
|
* Test for embedded
|
||||||
|
@ -78,6 +81,15 @@ public class TestEJBEmbedded extends SingleEMFTestCase {
|
||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEmbeddedMetaData() {
|
||||||
|
ClassMetaData ownerMeta =
|
||||||
|
JPAFacadeHelper.getMetaData(emf, EmbedOwner.class);
|
||||||
|
FieldMetaData fmd = ownerMeta.getField("embed");
|
||||||
|
ClassMetaData embeddedMeta = fmd.getDefiningMetaData();
|
||||||
|
assertNotNull(embeddedMeta);
|
||||||
|
assertNull(embeddedMeta.getField("transientField"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testNull() {
|
public void testNull() {
|
||||||
EntityManager em = emf.createEntityManager();
|
EntityManager em = emf.createEntityManager();
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.PersistentCollection;
|
||||||
|
import org.apache.openjpa.persistence.ManagedInterface;
|
||||||
|
import org.apache.openjpa.persistence.query.SimpleEntity;
|
||||||
|
|
||||||
|
@ManagedInterface
|
||||||
|
@Entity
|
||||||
|
public interface ManagedIface extends ManagedInterfaceSup {
|
||||||
|
public int getIntField();
|
||||||
|
public void setIntField(int i);
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
public ManagedInterfaceEmbed getEmbed();
|
||||||
|
public void setEmbed(ManagedInterfaceEmbed embed);
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.PERSIST)
|
||||||
|
public ManagedIface getSelf();
|
||||||
|
public void setSelf(ManagedIface iface);
|
||||||
|
|
||||||
|
@PersistentCollection
|
||||||
|
public Set<Integer> getSetInteger();
|
||||||
|
public void setSetInteger(Set<Integer> collection);
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.PERSIST)
|
||||||
|
public Set<SimpleEntity> getSetPC();
|
||||||
|
public void setSetPC(Set<SimpleEntity> collection);
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.PERSIST)
|
||||||
|
public Set<ManagedIface> getSetI();
|
||||||
|
public void setSetI(Set<ManagedIface> collection);
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.PERSIST)
|
||||||
|
public SimpleEntity getPC();
|
||||||
|
public void setPC(SimpleEntity pc);
|
||||||
|
|
||||||
|
public void unimplemented();
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.ManagedInterface;
|
||||||
|
|
||||||
|
@ManagedInterface
|
||||||
|
@Embeddable
|
||||||
|
public interface ManagedInterfaceEmbed {
|
||||||
|
public int getEmbedIntField();
|
||||||
|
public void setEmbedIntField(int i);
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ManagedInterfaceOwner {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private int intField;
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.PERSIST)
|
||||||
|
private ManagedInterfaceSup iface;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private ManagedInterfaceEmbed embed;
|
||||||
|
|
||||||
|
public int getIntField() {
|
||||||
|
return intField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntField(int i) {
|
||||||
|
intField = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagedInterfaceSup getIFace() {
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIFace(ManagedInterfaceSup iface) {
|
||||||
|
this.iface = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagedInterfaceEmbed getEmbed() {
|
||||||
|
return embed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmbed(ManagedInterfaceEmbed embed) {
|
||||||
|
this.embed = embed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.ManagedInterface;
|
||||||
|
|
||||||
|
@ManagedInterface
|
||||||
|
@Entity
|
||||||
|
public interface ManagedInterfaceSup {
|
||||||
|
@Id @GeneratedValue
|
||||||
|
public int getId();
|
||||||
|
public void setId(int id);
|
||||||
|
|
||||||
|
public int getIntFieldSup();
|
||||||
|
public void setIntFieldSup(int i);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.ManagedInterface;
|
||||||
|
|
||||||
|
@ManagedInterface
|
||||||
|
@Entity
|
||||||
|
public interface MixedInterface {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
public int getId();
|
||||||
|
public void setId(int id);
|
||||||
|
|
||||||
|
public int getIntField();
|
||||||
|
public void setIntField(int i);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class MixedInterfaceImpl implements MixedInterface {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private int intField;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIntField() {
|
||||||
|
return intField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntField(int i) {
|
||||||
|
intField = i;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
|
||||||
|
public interface NonMappedInterface {
|
||||||
|
public int getIntField();
|
||||||
|
|
||||||
|
public void setIntField(int i);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class NonMappedInterfaceImpl
|
||||||
|
implements NonMappedInterface {
|
||||||
|
private int mismatch;
|
||||||
|
|
||||||
|
public int getIntField() {
|
||||||
|
return mismatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntField(int i) {
|
||||||
|
mismatch = i;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.ManagedInterface;
|
||||||
|
|
||||||
|
@ManagedInterface
|
||||||
|
@Entity
|
||||||
|
public interface SimpleManagedInterface {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public int getId();
|
||||||
|
public void setId(int id);
|
||||||
|
|
||||||
|
public String getString();
|
||||||
|
public void setString(String s);
|
||||||
|
}
|
|
@ -0,0 +1,449 @@
|
||||||
|
package org.apache.openjpa.persistence.managedinterface;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.EntityNotFoundException;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||||
|
import org.apache.openjpa.persistence.JPAFacadeHelper;
|
||||||
|
import org.apache.openjpa.persistence.Extent;
|
||||||
|
import org.apache.openjpa.persistence.query.SimpleEntity;
|
||||||
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
import org.apache.openjpa.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class TestManagedInterfaces extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
super.setUp(SimpleEntity.class, ManagedInterfaceEmbed.class,
|
||||||
|
ManagedInterfaceSup.class, ManagedIface.class,
|
||||||
|
ManagedInterfaceOwner.class, MixedInterface.class,
|
||||||
|
MixedInterfaceImpl.class, NonMappedInterfaceImpl.class,
|
||||||
|
CLEAR_TABLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEmbeddedMetaData() {
|
||||||
|
emf.createEntityManager().close();
|
||||||
|
ClassMetaData ownerMeta = JPAFacadeHelper.getMetaData(emf,
|
||||||
|
ManagedIface.class);
|
||||||
|
ClassMetaData embeddedMeta = ownerMeta.getField("embed")
|
||||||
|
.getDefiningMetaData();
|
||||||
|
assertTrue(embeddedMeta.isManagedInterface());
|
||||||
|
assertTrue(embeddedMeta.isIntercepting());
|
||||||
|
|
||||||
|
ClassMetaData embeddableMeta = JPAFacadeHelper.getMetaData(emf,
|
||||||
|
ManagedInterfaceEmbed.class);
|
||||||
|
assertTrue(embeddableMeta.isManagedInterface());
|
||||||
|
assertTrue(embeddableMeta.isIntercepting());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testManagedInterface() throws Exception {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ManagedIface pc = em.createInstance(ManagedIface.class);
|
||||||
|
pc.setIntFieldSup(3);
|
||||||
|
pc.setIntField(4);
|
||||||
|
pc.setEmbed(em.createInstance(ManagedInterfaceEmbed.class));
|
||||||
|
|
||||||
|
pc.getEmbed().setEmbedIntField(5);
|
||||||
|
assertEquals(5, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
assertEquals(3, pc.getIntFieldSup());
|
||||||
|
assertEquals(4, pc.getIntField());
|
||||||
|
assertEquals(5, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.getTransaction().begin();
|
||||||
|
pc.setIntField(14);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager ();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
Query query = em.createQuery("select o from ManagedIface o " +
|
||||||
|
"where o.intField = 14");
|
||||||
|
pc = (ManagedIface) query.getSingleResult();
|
||||||
|
assertEquals(14, pc.getIntField());
|
||||||
|
em.remove(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
try {
|
||||||
|
assertNull(em.find(ManagedIface.class, oid));
|
||||||
|
} catch (EntityNotFoundException onfe) {}
|
||||||
|
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInterfaceOwner() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
ManagedInterfaceOwner pc = new ManagedInterfaceOwner();
|
||||||
|
pc.setIFace(em.createInstance(ManagedInterfaceSup.class));
|
||||||
|
pc.setEmbed(em.createInstance(ManagedInterfaceEmbed.class));
|
||||||
|
pc.getIFace().setIntFieldSup(3);
|
||||||
|
pc.getEmbed().setEmbedIntField(5);
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
pc = em.find(ManagedInterfaceOwner.class, oid);
|
||||||
|
assertEquals(3, pc.getIFace().getIntFieldSup());
|
||||||
|
assertEquals(5, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedInterfaceOwner.class, oid);
|
||||||
|
assertEquals(3, pc.getIFace().getIntFieldSup());
|
||||||
|
assertEquals(5, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
Query q = em.createQuery("select o from ManagedInterfaceOwner o " +
|
||||||
|
"where o.iface.intFieldSup = 3 and o.embed.embedIntField = 5");
|
||||||
|
pc = (ManagedInterfaceOwner) q.getSingleResult();
|
||||||
|
assertEquals(3, pc.getIFace().getIntFieldSup());
|
||||||
|
assertEquals(5, pc.getEmbed().getEmbedIntField());
|
||||||
|
|
||||||
|
pc.getIFace().setIntFieldSup(13);
|
||||||
|
pc.getEmbed().setEmbedIntField(15);
|
||||||
|
assertEquals(13, pc.getIFace().getIntFieldSup());
|
||||||
|
assertEquals(15, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedInterfaceOwner.class, oid);
|
||||||
|
assertEquals(13, pc.getIFace().getIntFieldSup());
|
||||||
|
assertEquals(15, pc.getEmbed().getEmbedIntField());
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCollection() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ManagedIface pc = em.createInstance(ManagedIface.class);
|
||||||
|
Set set = new HashSet();
|
||||||
|
set.add(new Integer(3));
|
||||||
|
set.add(new Integer(4));
|
||||||
|
set.add(new Integer(5));
|
||||||
|
pc.setSetInteger(set);
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetInteger();
|
||||||
|
assertEquals(3, set.size());
|
||||||
|
assertTrue(set.contains(new Integer(3)));
|
||||||
|
assertTrue(set.contains(new Integer(4)));
|
||||||
|
assertTrue(set.contains(new Integer(5)));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
set.remove(new Integer(4));
|
||||||
|
set.add(new Integer(14));
|
||||||
|
set.add(new Integer(15));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetInteger();
|
||||||
|
assertEquals(4, set.size());
|
||||||
|
assertTrue(set.contains(new Integer(3)));
|
||||||
|
assertTrue(set.contains(new Integer(5)));
|
||||||
|
assertTrue(set.contains(new Integer(14)));
|
||||||
|
assertTrue(set.contains(new Integer(15)));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
pc.setSetInteger(null);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetInteger();
|
||||||
|
assertTrue (set == null || set.size() == 0);
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCollectionPC() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ManagedIface pc = em.createInstance(ManagedIface.class);
|
||||||
|
Set set = new HashSet();
|
||||||
|
set.add(new SimpleEntity("a", "3"));
|
||||||
|
set.add(new SimpleEntity("b", "4"));
|
||||||
|
set.add(new SimpleEntity("c", "5"));
|
||||||
|
pc.setSetPC(set);
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetPC();
|
||||||
|
assertEquals(3, set.size());
|
||||||
|
Collection seen = new ArrayList();
|
||||||
|
SimpleEntity rel;
|
||||||
|
SimpleEntity toRem = null;
|
||||||
|
for (Iterator it = set.iterator(); it.hasNext();) {
|
||||||
|
rel = (SimpleEntity) it.next();
|
||||||
|
seen.add(rel.getName());
|
||||||
|
if (rel.getValue().equals("4"))
|
||||||
|
toRem = rel;
|
||||||
|
}
|
||||||
|
assertEquals(3, seen.size());
|
||||||
|
assertTrue(seen.contains("a"));
|
||||||
|
assertTrue(seen.contains("b"));
|
||||||
|
assertTrue(seen.contains("c"));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
assertNotNull(toRem);
|
||||||
|
set.remove(toRem);
|
||||||
|
set.add(new SimpleEntity("x", "14"));
|
||||||
|
set.add(new SimpleEntity("y", "15"));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetPC();
|
||||||
|
assertEquals(4, set.size());
|
||||||
|
seen.clear();
|
||||||
|
for (Iterator it = set.iterator(); it.hasNext();) {
|
||||||
|
rel = (SimpleEntity) it.next();
|
||||||
|
seen.add(rel.getName());
|
||||||
|
}
|
||||||
|
assertEquals(4, seen.size());
|
||||||
|
assertTrue(seen.contains("a"));
|
||||||
|
assertTrue(seen.contains("c"));
|
||||||
|
assertTrue(seen.contains("x"));
|
||||||
|
assertTrue(seen.contains("y"));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
pc.setSetPC(null);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetPC();
|
||||||
|
assertTrue (set == null || set.size() == 0);
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCollectionInterfaces() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ManagedIface pc = em.createInstance(ManagedIface.class);
|
||||||
|
Set set = new HashSet();
|
||||||
|
set.add(createInstance(em, 3));
|
||||||
|
set.add(createInstance(em, 4));
|
||||||
|
set.add(createInstance(em, 5));
|
||||||
|
pc.setSetI(set);
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetI();
|
||||||
|
assertEquals(3, set.size());
|
||||||
|
Collection seen = new ArrayList();
|
||||||
|
ManagedIface rel = null;
|
||||||
|
ManagedIface toRem = null;
|
||||||
|
for (Iterator it = set.iterator(); it.hasNext();) {
|
||||||
|
rel = (ManagedIface) it.next();
|
||||||
|
seen.add(new Integer(rel.getIntField()));
|
||||||
|
if (rel.getIntField() == 4)
|
||||||
|
toRem = rel;
|
||||||
|
}
|
||||||
|
assertEquals(3, seen.size());
|
||||||
|
assertTrue(seen.contains(new Integer(3)));
|
||||||
|
assertTrue(seen.contains(new Integer(4)));
|
||||||
|
assertTrue(seen.contains(new Integer(5)));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
assertNotNull(toRem);
|
||||||
|
set.remove(toRem);
|
||||||
|
set.add(createInstance(em, 14));
|
||||||
|
set.add(createInstance(em, 15));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetI();
|
||||||
|
assertEquals(4, set.size());
|
||||||
|
seen.clear();
|
||||||
|
for (Iterator it = set.iterator(); it.hasNext();) {
|
||||||
|
rel = (ManagedIface) it.next();
|
||||||
|
seen.add(new Integer(rel.getIntField()));
|
||||||
|
}
|
||||||
|
assertEquals(4, seen.size());
|
||||||
|
assertTrue(seen.contains(new Integer(3)));
|
||||||
|
assertTrue(seen.contains(new Integer(5)));
|
||||||
|
assertTrue(seen.contains(new Integer(14)));
|
||||||
|
assertTrue(seen.contains(new Integer(15)));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
pc.setSetPC(null);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
set = pc.getSetPC();
|
||||||
|
assertTrue (set == null || set.size() == 0);
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMixedQuery() {
|
||||||
|
createMixed();
|
||||||
|
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
try {
|
||||||
|
Query q = em.createQuery("select o from MixedInterface o " +
|
||||||
|
"where o.intField = 4");
|
||||||
|
Collection c = q.getResultList();
|
||||||
|
Set seen = new HashSet();
|
||||||
|
assertEquals(2, c.size());
|
||||||
|
MixedInterface pc;
|
||||||
|
for (Iterator it = c.iterator(); it.hasNext();) {
|
||||||
|
pc = (MixedInterface) it.next();
|
||||||
|
assertEquals(4, pc.getIntField());
|
||||||
|
seen.add(pc.getClass());
|
||||||
|
}
|
||||||
|
assertEquals(2, seen.size());
|
||||||
|
|
||||||
|
fail("OPENJPA-481");
|
||||||
|
} catch (PersistenceException e) {
|
||||||
|
// expected
|
||||||
|
} finally {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueryForMixedInterfaceImpls() {
|
||||||
|
createMixed();
|
||||||
|
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
Query q = em.createQuery("select o from MixedInterfaceImpl o " +
|
||||||
|
"where o.intField = 4");
|
||||||
|
MixedInterface pc = (MixedInterface) q.getSingleResult();
|
||||||
|
assertEquals(4, pc.getIntField());
|
||||||
|
assertTrue(pc instanceof MixedInterfaceImpl);
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMixedExtent() {
|
||||||
|
createMixed();
|
||||||
|
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
Extent e = em.createExtent(MixedInterface.class, true);
|
||||||
|
Set seen = new HashSet();
|
||||||
|
int size = 0;
|
||||||
|
for (Iterator it = e.iterator(); it.hasNext();) {
|
||||||
|
seen.add(it.next().getClass());
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
assertEquals(3, size);
|
||||||
|
assertEquals(2, seen.size());
|
||||||
|
|
||||||
|
e = em.createExtent(MixedInterface.class, false);
|
||||||
|
seen = new HashSet();
|
||||||
|
size = 0;
|
||||||
|
for (Iterator it = e.iterator(); it.hasNext();) {
|
||||||
|
seen.add(it.next().getClass());
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
assertEquals(1, size);
|
||||||
|
assertNotEquals(MixedInterfaceImpl.class, seen.iterator().next());
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMixed() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
MixedInterface pc = em.createInstance(MixedInterface.class);
|
||||||
|
pc.setIntField(4);
|
||||||
|
em.persist(pc);
|
||||||
|
pc = new MixedInterfaceImpl();
|
||||||
|
pc.setIntField(4);
|
||||||
|
em.persist(pc);
|
||||||
|
pc = new MixedInterfaceImpl();
|
||||||
|
pc.setIntField(8);
|
||||||
|
em.persist(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnimplementedThrowsException() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
ManagedIface pc = createInstance(em, 1);
|
||||||
|
try {
|
||||||
|
pc.unimplemented();
|
||||||
|
fail("Exception expected.");
|
||||||
|
} catch (UnsupportedOperationException uoe) {} // good
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNonMappedCreateInstanceException() {
|
||||||
|
// OpenJPA's support of non-mapped interfaces differs from JDO support;
|
||||||
|
// there is no special query or relation support for non-mapped
|
||||||
|
// interfaces in OpenJPA at this time.
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
|
try {
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.createInstance(NonMappedInterface.class);
|
||||||
|
fail("IllegalArgumentException expected");
|
||||||
|
} catch (IllegalArgumentException e) {} // good
|
||||||
|
if (em != null)
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDetach() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ManagedIface pc = createInstance(em, 4);
|
||||||
|
em.persist(pc);
|
||||||
|
Object oid = em.getObjectId(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
ManagedIface pcx = em.find(ManagedIface.class, oid);
|
||||||
|
pc = em.detach(pcx);
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
assertTrue(em.isDetached(pc));
|
||||||
|
pc.setIntField(7);
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.merge(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(ManagedIface.class, oid);
|
||||||
|
assertEquals(7, pc.getIntField());
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ManagedIface createInstance(OpenJPAEntityManager em, int i) {
|
||||||
|
ManagedIface pc = em.createInstance(ManagedIface.class);
|
||||||
|
pc.setIntField(i);
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* 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.managedinterface;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
import org.apache.openjpa.persistence.JPAFacadeHelper;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||||
|
import org.apache.openjpa.persistence.query.SimpleEntity;
|
||||||
|
import org.apache.openjpa.kernel.AbstractBrokerFactory;
|
||||||
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
|
|
||||||
|
public class TestSimpleManagedInterface
|
||||||
|
extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
setUp(SimpleManagedInterface.class, SimpleEntity.class, CLEAR_TABLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMetaDataRepository() {
|
||||||
|
AbstractBrokerFactory bf =
|
||||||
|
(AbstractBrokerFactory) JPAFacadeHelper.toBrokerFactory(emf);
|
||||||
|
bf.makeReadOnly();
|
||||||
|
MetaDataRepository repos = bf.getConfiguration()
|
||||||
|
.getMetaDataRepositoryInstance();
|
||||||
|
ClassMetaData meta = repos.getMetaData(SimpleManagedInterface.class,
|
||||||
|
null, false);
|
||||||
|
assertNotNull(meta);
|
||||||
|
assertTrue(meta.isManagedInterface());
|
||||||
|
assertEquals(SimpleManagedInterface.class, meta.getDescribedType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInterfaceImplGeneration() {
|
||||||
|
((AbstractBrokerFactory) JPAFacadeHelper.toBrokerFactory(emf))
|
||||||
|
.makeReadOnly();
|
||||||
|
// load metadata to trigger instance creation
|
||||||
|
ClassMetaData meta = JPAFacadeHelper.getMetaData(emf,
|
||||||
|
SimpleManagedInterface.class);
|
||||||
|
assertEquals(SimpleManagedInterface.class, meta.getDescribedType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicOperations() {
|
||||||
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
SimpleManagedInterface pc =
|
||||||
|
em.createInstance(SimpleManagedInterface.class);
|
||||||
|
pc.setId(17);
|
||||||
|
pc.setString("hello!");
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(pc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
pc = em.find(SimpleManagedInterface.class, 17);
|
||||||
|
assertNotNull(pc);
|
||||||
|
em.getTransaction().begin();
|
||||||
|
pc.setString("updated");
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.remove(em.getReference(SimpleManagedInterface.class, 17));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJPQL() {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
assertEquals(0, em.createQuery("select o from SimpleManagedInterface o")
|
||||||
|
.getResultList().size());
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -172,6 +172,7 @@ public class AnnotationPersistenceMetaDataParser
|
||||||
_tags.put(KeyType.class, KEY_TYPE);
|
_tags.put(KeyType.class, KEY_TYPE);
|
||||||
_tags.put(LoadFetchGroup.class, LOAD_FETCH_GROUP);
|
_tags.put(LoadFetchGroup.class, LOAD_FETCH_GROUP);
|
||||||
_tags.put(LRS.class, LRS);
|
_tags.put(LRS.class, LRS);
|
||||||
|
_tags.put(ManagedInterface.class, MANAGED_INTERFACE);
|
||||||
_tags.put(ReadOnly.class, READ_ONLY);
|
_tags.put(ReadOnly.class, READ_ONLY);
|
||||||
_tags.put(Type.class, TYPE);
|
_tags.put(Type.class, TYPE);
|
||||||
}
|
}
|
||||||
|
@ -572,6 +573,10 @@ public class AnnotationPersistenceMetaDataParser
|
||||||
if (isMetaDataMode())
|
if (isMetaDataMode())
|
||||||
fgs = ((FetchGroups) anno).value();
|
fgs = ((FetchGroups) anno).value();
|
||||||
break;
|
break;
|
||||||
|
case MANAGED_INTERFACE:
|
||||||
|
if (isMetaDataMode())
|
||||||
|
parseManagedInterface(meta, (ManagedInterface) anno);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedException(_loc.get("unsupported", _cls,
|
throw new UnsupportedException(_loc.get("unsupported", _cls,
|
||||||
anno.toString()));
|
anno.toString()));
|
||||||
|
@ -595,7 +600,8 @@ public class AnnotationPersistenceMetaDataParser
|
||||||
// scan possibly non-PC hierarchy for callbacks.
|
// scan possibly non-PC hierarchy for callbacks.
|
||||||
// redundant for PC superclass but we don't know that yet
|
// redundant for PC superclass but we don't know that yet
|
||||||
// so let LifecycleMetaData determine that
|
// so let LifecycleMetaData determine that
|
||||||
if (!Object.class.equals(_cls.getSuperclass())) {
|
if (_cls.getSuperclass() != null &&
|
||||||
|
!Object.class.equals(_cls.getSuperclass())) {
|
||||||
recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
|
recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
|
||||||
null, true, false, getRepository()), null, true);
|
null, true, false, getRepository()), null, true);
|
||||||
}
|
}
|
||||||
|
@ -750,6 +756,11 @@ public class AnnotationPersistenceMetaDataParser
|
||||||
meta.setDataCacheName(null);
|
meta.setDataCacheName(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseManagedInterface(ClassMetaData meta,
|
||||||
|
ManagedInterface iface) {
|
||||||
|
meta.setManagedInterface(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse @DetachedState. The annotation may be null.
|
* Parse @DetachedState. The annotation may be null.
|
||||||
*/
|
*/
|
||||||
|
@ -798,6 +809,10 @@ public class AnnotationPersistenceMetaDataParser
|
||||||
public static Collection<LifecycleCallbacks>[] parseCallbackMethods
|
public static Collection<LifecycleCallbacks>[] parseCallbackMethods
|
||||||
(Class cls, Collection<LifecycleCallbacks>[] callbacks, boolean sups,
|
(Class cls, Collection<LifecycleCallbacks>[] callbacks, boolean sups,
|
||||||
boolean listener, MetaDataRepository repos) {
|
boolean listener, MetaDataRepository repos) {
|
||||||
|
|
||||||
|
if (cls == null)
|
||||||
|
throw new IllegalArgumentException("cls cannot be null");
|
||||||
|
|
||||||
// first sort / filter based on inheritance
|
// first sort / filter based on inheritance
|
||||||
Set<Method> methods = new TreeSet<Method>(MethodComparator.
|
Set<Method> methods = new TreeSet<Method>(MethodComparator.
|
||||||
getInstance());
|
getInstance());
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The annotated interface should be treated as a managed interface by OpenJPA.
|
||||||
|
* New instances of this type can be created by invoking
|
||||||
|
* {@link OpenJPAEntityManager#createInstance(Class)}.
|
||||||
|
* Interfaces with this annotation should also be annotated with one of the JPA
|
||||||
|
* entity annotations ({@link javax.persistence.Entity @Entity},
|
||||||
|
* {@link javax.persistence.MappedSuperclass @MappedSuperclass},
|
||||||
|
* or {@link javax.persistence.Embeddable @Embeddable}).
|
||||||
|
*
|
||||||
|
* @since 1.1.0
|
||||||
|
* @published
|
||||||
|
*/
|
||||||
|
@Target({ TYPE })
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface ManagedInterface {
|
||||||
|
}
|
|
@ -77,6 +77,7 @@ public enum MetaDataTag {
|
||||||
KEY_TYPE,
|
KEY_TYPE,
|
||||||
LOAD_FETCH_GROUP,
|
LOAD_FETCH_GROUP,
|
||||||
LRS,
|
LRS,
|
||||||
|
MANAGED_INTERFACE,
|
||||||
READ_ONLY,
|
READ_ONLY,
|
||||||
TYPE,
|
TYPE,
|
||||||
}
|
}
|
||||||
|
|
|
@ -780,8 +780,11 @@ public interface OpenJPAEntityManager
|
||||||
* create a subclass of the type that does implement
|
* create a subclass of the type that does implement
|
||||||
* {@link org.apache.openjpa.enhance.PersistenceCapable}, and will attempt
|
* {@link org.apache.openjpa.enhance.PersistenceCapable}, and will attempt
|
||||||
* to redefine the methods in <code>cls</code> to enable persistent
|
* to redefine the methods in <code>cls</code> to enable persistent
|
||||||
* attribute tracking. Otherwise, this will return an instance of the
|
* attribute tracking. Otherwise, if <code>cls</code> is a managed type,
|
||||||
* specified class.
|
* this will return an instance of the specified class.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if <code>cls</code> is not a managed
|
||||||
|
* type or interface.
|
||||||
*/
|
*/
|
||||||
public <T> T createInstance(Class<T> cls);
|
public <T> T createInstance(Class<T> cls);
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,8 @@ public class PersistenceMetaDataDefaults
|
||||||
J2DoPriv5Helper.getDeclaredFieldsAction(cls))))
|
J2DoPriv5Helper.getDeclaredFieldsAction(cls))))
|
||||||
access |= ClassMetaData.ACCESS_FIELD;
|
access |= ClassMetaData.ACCESS_FIELD;
|
||||||
if (usesAccess((Method[]) AccessController.doPrivileged(
|
if (usesAccess((Method[]) AccessController.doPrivileged(
|
||||||
J2DoPriv5Helper.getDeclaredMethodsAction(cls))))
|
J2DoPriv5Helper.getDeclaredMethodsAction(cls)))
|
||||||
|
|| cls.isInterface()) // OpenJPA managed ifaces must use prop access
|
||||||
access |= ClassMetaData.ACCESS_PROPERTY;
|
access |= ClassMetaData.ACCESS_PROPERTY;
|
||||||
return (access == 0) ? getAccessType(cls.getSuperclass()) : access;
|
return (access == 0) ? getAccessType(cls.getSuperclass()) : access;
|
||||||
}
|
}
|
||||||
|
|
|
@ -483,6 +483,43 @@ a javaagent or in a Java 6 environment.
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
<section id="ref_guide_pc_interfaces">
|
||||||
|
<title>Managed Interfaces</title>
|
||||||
|
<indexterm zone="ref_guide_pc_interfaces">
|
||||||
|
<primary>interfaces</primary>
|
||||||
|
<secondary>managed</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<para>
|
||||||
|
OpenJPA's managed interface feature allows you to define your object model
|
||||||
|
entirely in terms of interfaces, instead of concrete classes. To use this
|
||||||
|
feature, you must annotate your managed interfaces with the
|
||||||
|
<classname>ManagedInterface</classname> annotation, and use the
|
||||||
|
<literal>OpenJPAEntityManager.createInstance(Class)</literal> method to
|
||||||
|
create new records. Note that <literal>createInstance()</literal> returns
|
||||||
|
unmanaged instances; you must pass them to
|
||||||
|
<literal>EntityManager.persist()</literal> to store them in the database.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
@ManagedInterface
|
||||||
|
public interface PersonIface {
|
||||||
|
@Id @GeneratedValue
|
||||||
|
int getId();
|
||||||
|
void setId(int id);
|
||||||
|
|
||||||
|
// implicitly persistent per JPA property rules
|
||||||
|
String getName();
|
||||||
|
void setName(String name);
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<programlisting>
|
||||||
|
OpenJPAEntityManager em = ...;
|
||||||
|
PersonIface person = em.createInstance(PersonIface.class);
|
||||||
|
person.setName("Homer Simpson");
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(person);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
<section id="ref_guide_pc_oid">
|
<section id="ref_guide_pc_oid">
|
||||||
<title>
|
<title>
|
||||||
Object Identity
|
Object Identity
|
||||||
|
|
Loading…
Reference in New Issue