use of org.eclipse.persistence.sessions.CopyGroup in project eclipselink by eclipse-ee4j.
the class SimpleSerializeFetchGroupTests method copyWithOrWithoutPk.
void copyWithOrWithoutPk(boolean noPk, boolean useFullGroup) {
CopyGroup group = new CopyGroup();
if (noPk) {
// setShouldResetPrimaryKey set to true means that:
// pk would not be copied - unless explicitly specified in the group;
// copy would not have a fetch group
group.setShouldResetPrimaryKey(true);
// setShouldResetVersion set to true means that
// version would not be copied - unless explicitly specified in the group;
group.setShouldResetVersion(true);
}
// Copy only the attributes specified
group.cascadeTree();
// note that
// default value shouldResetPrimaryKey==false causes pk to copied, too;
// default value shouldResetVersion==false causes version to be copied, too.
group.addAttribute("firstName");
group.addAttribute("lastName");
group.addAttribute("gender");
group.addAttribute("period");
group.addAttribute("salary");
if (useFullGroup) {
// copy group contains all the attributes defined in Address class
CopyGroup address = addressDescriptor.getFetchGroupManager().createFullFetchGroup().toCopyGroup();
// attribute "employees" removed from the group
address.removeAttribute("employees");
if (noPk) {
// pk attribute "ID" removed from the group - not that it's necessary to explicitly remove it:
// setShouldResetPrimaryKey(true) would not remove explicitly specified in the group pk.
address.removeAttribute("id");
// note that default value shouldResetPrimaryKey==false would have resulted in copying the pk (that would be equivalent of adding the removed "ID" attribute back to the group).
address.setShouldResetPrimaryKey(true);
address.setShouldResetVersion(true);
}
group.addAttribute("address", address);
// copy group contains all the attributes defined in PhoneNumber class
CopyGroup phones = phoneDescriptor.getFetchGroupManager().createFullFetchGroup().toCopyGroup();
if (noPk) {
// the only goal of setting shouldResetPrimaryKey to true here is to avoid a FetchGroup being assigned to phone's copy.
// Note that because both pk components ("owner" and "type") are part of the copy group they still will be copied:
// the phone's copy will have the same type as original and it's owner will be original's owner's copy.
phones.setShouldResetPrimaryKey(true);
}
if (!noPk) {
// to avoid instantiating the whole owner
phones.addAttribute("owner.id");
}
group.addAttribute("phoneNumbers", phones);
} else {
// implicitly created sub CopyGroups address and phoneNumbers will have the same shouldReset flags values as their master CopyGroup.
group.addAttribute("address.country");
group.addAttribute("address.province");
group.addAttribute("address.street");
group.addAttribute("address.postalCode");
group.addAttribute("address.city");
if (noPk) {
group.addAttribute("phoneNumbers.owner");
} else {
// to avoid instantiating the whole owner
group.addAttribute("phoneNumbers.owner.id");
}
group.addAttribute("phoneNumbers.type");
group.addAttribute("phoneNumbers.areaCode");
group.addAttribute("phoneNumbers.number");
}
EntityManager em = createEntityManager("fieldaccess");
try {
beginTransaction(em);
Employee emp = minimumEmployee(em);
Employee empCopy = (Employee) em.unwrap(JpaEntityManager.class).copy(emp, group);
if (noPk) {
assertNoFetchGroup(empCopy);
assertNoFetchGroup(empCopy.getAddress());
for (PhoneNumber phoneCopy : empCopy.getPhoneNumbers()) {
assertNoFetchGroup(phoneCopy);
}
// Persist the employee copy
em.persist(empCopy);
} else {
FetchGroup fetchGroup = group.toFetchGroup();
// the following call adds pk and version, verifies that all attribute names correct.
employeeDescriptor.getFetchGroupManager().prepareAndVerify(fetchGroup);
// copyEmp, its address and phones each should have an EntityFetchGroup corresponding to the respective copyGroup.
assertFetched(empCopy, fetchGroup);
EntityFetchGroup addressEntityFetchGroup = addressDescriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup.getGroup("address"));
if (addressEntityFetchGroup == null) {
assertNoFetchGroup(empCopy.getAddress());
} else {
assertFetched(empCopy.getAddress(), addressEntityFetchGroup);
}
EntityFetchGroup phonesEntityFetchGroup = phoneDescriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup.getGroup("phoneNumbers"));
for (PhoneNumber phoneCopy : empCopy.getPhoneNumbers()) {
if (phonesEntityFetchGroup == null) {
assertNoFetchGroup(phoneCopy);
} else {
assertFetched(phoneCopy, phonesEntityFetchGroup);
}
}
// to cause updates let's change something:
// in Employee table
empCopy.setFirstName((empCopy.getFirstName() != null ? empCopy.getFirstName() : "") + "_NEW");
// in Salary table
empCopy.setSalary(empCopy.getSalary() * 2 + 1);
// in Address
empCopy.getAddress().setCountry((empCopy.getAddress().getCountry() != null ? empCopy.getAddress().getCountry() : "") + "_NEW");
// in each Phone
for (PhoneNumber phoneCopy : empCopy.getPhoneNumbers()) {
if (phoneCopy.getAreaCode() != null && phoneCopy.getAreaCode().equals("000")) {
phoneCopy.setAreaCode("111");
} else {
phoneCopy.setAreaCode("000");
}
}
em.merge(empCopy);
}
// Insert a new row into Employee, Salary, Address, and a row for each Phone
int nExpectedInsertsOrUpdates = 3 + empCopy.getPhoneNumbers().size();
int nExpectedInserts, nExpectedUpdates;
if (noPk) {
nExpectedInserts = nExpectedInsertsOrUpdates;
// table sequence might have been updated
nExpectedUpdates = getQuerySQLTracker(em).getTotalSQLUPDATECalls();
} else {
nExpectedInserts = 0;
nExpectedUpdates = nExpectedInsertsOrUpdates;
}
// Flush the changes to the database
em.flush();
assertEquals(nExpectedInserts, getQuerySQLTracker(em).getTotalSQLINSERTCalls());
assertEquals(nExpectedUpdates, getQuerySQLTracker(em).getTotalSQLUPDATECalls());
} finally {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
}
}
use of org.eclipse.persistence.sessions.CopyGroup in project eclipselink by eclipse-ee4j.
the class AbstractSession method copy.
/**
* PUBLIC:
* Return a complete copy of the object or of collection of objects.
* In case of collection all members should be either entities of the same type
* or have a common inheritance hierarchy mapped root class.
* This can be used to obtain a scratch copy of an object,
* or for templatizing an existing object into another new object.
* If there are no attributes in the group
* then the object and all of its privately owned parts will be copied.
* Otherwise only the attributes included into the group will be copied.
*/
@Override
public Object copy(Object originalObjectOrObjects, AttributeGroup group) {
if (originalObjectOrObjects == null) {
return null;
}
CopyGroup copyGroup = group.toCopyGroup();
copyGroup.setSession(this);
if (originalObjectOrObjects instanceof Collection) {
// it's a collection - make sure all elements use the same instance of CopyGroup.
Collection originalCollection = (Collection) originalObjectOrObjects;
Collection copies;
if (originalCollection instanceof List) {
copies = new ArrayList();
} else {
copies = new HashSet();
}
Iterator it = originalCollection.iterator();
while (it.hasNext()) {
copies.add(copyInternal(it.next(), copyGroup));
}
return copies;
}
// it's not a collection
return copyInternal(originalObjectOrObjects, copyGroup);
}
use of org.eclipse.persistence.sessions.CopyGroup in project eclipselink by eclipse-ee4j.
the class InheritedModelJunitTest method testCopyMapKeyMap.
// Bug 406957 - Copy fails on AggregateCollectionMapping and on map with @MapKeyColumn
public void testCopyMapKeyMap() {
Calendar cal = Calendar.getInstance();
BeerConsumer consumer = new BeerConsumer();
consumer.setId(1);
consumer.setName("A");
Heineken heineken = new Heineken();
heineken.setAlcoholContent(5.0);
heineken.setId(11);
Date date = cal.getTime();
consumer.addHeinekenBeerToConsume(heineken, date);
EntityManager em = createEntityManager();
CopyGroup copyAll = new CopyGroup();
copyAll.cascadeAllParts();
BeerConsumer consumerCopy = (BeerConsumer) JpaHelper.getEntityManager(em).copy(consumer, copyAll);
if (consumerCopy.getHeinekenBeersToConsume().size() != consumer.getHeinekenBeersToConsume().size()) {
fail("consumerCopy.getHeinekenBeersToConsume().size() = " + consumerCopy.getHeinekenBeersToConsume().size() + "; " + consumer.getHeinekenBeersToConsume().size() + " was expected");
}
if (consumerCopy.getHeinekenBeersToConsume() == consumer.getHeinekenBeersToConsume()) {
fail("consumerCopy.getHeinekenBeersToConsume() == consumer.getHeinekenBeersToConsume()");
}
Map.Entry<Date, Heineken> entry = (Map.Entry<Date, Heineken>) consumerCopy.getHeinekenBeersToConsume().entrySet().iterator().next();
Date dateCopy = entry.getKey();
Heineken heinekenCopy = entry.getValue();
if (!date.equals(dateCopy)) {
fail("!date.equals(dateCopy)");
}
if (heineken == heinekenCopy) {
fail("heineken == heinekenCopy");
}
if (heineken.getAlcoholContent() != heinekenCopy.getAlcoholContent()) {
fail("heineken.getAlcoholContent() != heinekenCopy.getAlcoholContent()");
}
}
use of org.eclipse.persistence.sessions.CopyGroup in project eclipselink by eclipse-ee4j.
the class EntityManagerJUnitTestSuite method testObjectReferencedInBothEmAndSharedCache_ObjectReferenceMappingVH.
// Bug 336280 - Same object referenced from both EM cache and shared cache
public void testObjectReferencedInBothEmAndSharedCache_ObjectReferenceMappingVH() {
EntityManager em = createEntityManager();
Employee emp = new Employee();
emp.setFirstName("Manager");
Employee emp1 = new Employee();
emp1.setFirstName("1");
emp.addManagedEmployee(emp1);
Employee emp2 = new Employee();
emp2.setFirstName("2");
emp.addManagedEmployee(emp2);
DatabaseSessionImpl dbs = null;
beginTransaction(em);
em.persist(emp);
// in JTA case transaction required to obtain ServerSession through getServersession method.
dbs = getDatabaseSession();
commitTransaction(em);
CopyGroup copyGroup = new CopyGroup();
copyGroup.cascadeAllParts();
dbs.copy(emp, copyGroup);
Set originalObjects = copyGroup.getCopies().keySet();
// copyGroup cascades through all mappings.
// originalObjects should consist of just three objects: emp, emp1, emp2.
// However if manager_vh is wrapped around manager instance from the shared cache (empShared),
// the size will be 6: emp, emp1, emp2 and empShared, emp1Shared, emp2Shared.
assertTrue(originalObjects.size() == 3);
}
use of org.eclipse.persistence.sessions.CopyGroup in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method copyObject.
/**
* Return a copy of the object.
* This is NOT used for unit of work but for templatizing an object.
* The depth and primary key reseting are passed in.
*/
public Object copyObject(Object original, CopyGroup copyGroup) {
Object copy = copyGroup.getCopies().get(original);
if (copyGroup.shouldCascadeTree()) {
FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
if (fetchGroupManager != null) {
// empty copy group means all the attributes should be copied - don't alter it.
if (copyGroup.hasItems()) {
// by default add primary key attribute(s) if not already in the group
if (!copyGroup.shouldResetPrimaryKey()) {
for (DatabaseMapping mapping : this.primaryKeyMappings) {
String name = mapping.getAttributeName();
if (!copyGroup.containsAttributeInternal(name)) {
copyGroup.addAttribute(name);
}
}
} else {
for (DatabaseMapping mapping : this.primaryKeyMappings) {
if (mapping.isForeignReferenceMapping()) {
String name = mapping.getAttributeName();
if (!copyGroup.containsAttributeInternal(name)) {
copyGroup.addAttribute(name);
}
}
}
}
// by default version attribute if not already in the group
if (!copyGroup.shouldResetVersion()) {
if (this.lockAttribute != null) {
if (!copyGroup.containsAttributeInternal(this.lockAttribute)) {
copyGroup.addAttribute(this.lockAttribute);
}
}
}
FetchGroup fetchGroup = fetchGroupManager.getObjectFetchGroup(original);
if (fetchGroup != null) {
if (!fetchGroup.getAttributeNames().containsAll(copyGroup.getAttributeNames())) {
// trigger fetch group if it does not contain all attributes of the copy group.
fetchGroup.onUnfetchedAttribute((FetchGroupTracker) original, null);
}
}
}
// Entity fetch group currently set on copyObject
EntityFetchGroup existingEntityFetchGroup = null;
if (copy != null) {
Object[] copyArray = (Object[]) copy;
// copy of the original
copy = copyArray[0];
// A set of CopyGroups that have visited.
Set<CopyGroup> visitedCopyGroups = (Set<CopyGroup>) copyArray[1];
if (visitedCopyGroups.contains(copyGroup)) {
// original has been already visited with this copyGroup - leave
return copy;
} else {
visitedCopyGroups.add(copyGroup);
}
existingEntityFetchGroup = fetchGroupManager.getObjectEntityFetchGroup(copy);
}
// Entity fetch group that will be assigned to copyObject
EntityFetchGroup newEntityFetchGroup = null;
// Attributes to be visited - only reference mappings will be visited.
// If null then all attributes should be visited.
Set<String> attributesToVisit = copyGroup.getAttributeNames();
// Attributes to be copied
Set<String> attributesToCopy = attributesToVisit;
boolean shouldCopyAllAttributes = false;
boolean shouldAssignNewEntityFetchGroup = false;
if (copy != null && existingEntityFetchGroup == null) {
// all attributes have been already copied
attributesToCopy = null;
} else {
// Entity fetch group corresponding to copyPolicy.
// Note that empty, or null, or containing all arguments attributesToCopy
// results in copyGroupFetchGroup = null;
EntityFetchGroup copyGroupEntityFetchGroup = fetchGroupManager.getEntityFetchGroup(attributesToCopy);
if (copyGroupEntityFetchGroup == null) {
// all attributes will be copied
shouldCopyAllAttributes = true;
}
if (copy != null) {
if (copyGroupEntityFetchGroup != null) {
if (!copyGroup.shouldResetPrimaryKey()) {
if (!existingEntityFetchGroup.getAttributeNames().containsAll(attributesToCopy)) {
// Entity fetch group that will be assigned to copy object
newEntityFetchGroup = fetchGroupManager.flatUnionFetchGroups(existingEntityFetchGroup, copyGroupEntityFetchGroup, false);
shouldAssignNewEntityFetchGroup = true;
}
}
attributesToCopy = new HashSet(attributesToCopy);
attributesToCopy.removeAll(existingEntityFetchGroup.getAttributeNames());
}
} else {
// copy does not exist - create it
copy = copyGroup.getSession().getDescriptor(original).getObjectBuilder().buildNewInstance();
Set<CopyGroup> visitedCopyGroups = new HashSet();
visitedCopyGroups.add(copyGroup);
copyGroup.getCopies().put(original, new Object[] { copy, visitedCopyGroups });
if (!copyGroup.shouldResetPrimaryKey()) {
newEntityFetchGroup = copyGroupEntityFetchGroup;
shouldAssignNewEntityFetchGroup = true;
}
}
}
if (shouldAssignNewEntityFetchGroup) {
fetchGroupManager.setObjectFetchGroup(copy, newEntityFetchGroup, null);
}
for (DatabaseMapping mapping : getDescriptor().getMappings()) {
String name = mapping.getAttributeName();
boolean shouldCopy = shouldCopyAllAttributes || (attributesToCopy != null && attributesToCopy.contains(name));
boolean shouldVisit = attributesToVisit == null || attributesToVisit.contains(name);
if (shouldCopy || shouldVisit) {
boolean isVisiting = false;
// unless it's a reference mapping pass copyGroup - just to carry the session.
CopyGroup mappingCopyGroup = copyGroup;
if (mapping.isForeignReferenceMapping()) {
ForeignReferenceMapping frMapping = (ForeignReferenceMapping) mapping;
ClassDescriptor referenceDescriptor = frMapping.getReferenceDescriptor();
if (referenceDescriptor != null) {
isVisiting = true;
mappingCopyGroup = copyGroup.getGroup(name);
if (mappingCopyGroup == null) {
FetchGroupManager referenceFetchGroupManager = referenceDescriptor.getFetchGroupManager();
if (referenceFetchGroupManager != null) {
EntityFetchGroup nonReferenceEntityFetchGroup = referenceFetchGroupManager.getNonReferenceEntityFetchGroup(copyGroup.shouldResetPrimaryKey(), copyGroup.shouldResetVersion());
if (nonReferenceEntityFetchGroup != null) {
mappingCopyGroup = nonReferenceEntityFetchGroup.toCopyGroup();
} else {
// null nonReferenceEntityFetchGroup is equivalent to containing all attributes:
// create a new empty CopyGroup.
mappingCopyGroup = new CopyGroup();
mappingCopyGroup.shouldCascadeTree();
}
} else {
// TODO: would that work?
mappingCopyGroup = new CopyGroup();
mappingCopyGroup.dontCascade();
isVisiting = false;
}
mappingCopyGroup.setCopies(copyGroup.getCopies());
mappingCopyGroup.setShouldResetPrimaryKey(copyGroup.shouldResetPrimaryKey());
mappingCopyGroup.setShouldResetVersion(copyGroup.shouldResetVersion());
}
mappingCopyGroup.setSession(copyGroup.getSession());
}
} else if (mapping.isAggregateObjectMapping()) {
mappingCopyGroup = new CopyGroup();
}
if (shouldCopy || isVisiting) {
// TODO: optimization: (even when isVisiting == true) redefine buildCopy to take shouldCopy and don't copy if not required.
mapping.buildCopy(copy, original, mappingCopyGroup);
}
}
}
} else {
// fetchGroupManager == null
// TODO
}
} else {
// ! copyGroup.shouldCascadeTree()
if (copy != null) {
return copy;
}
copy = instantiateClone(original, copyGroup.getSession());
copyGroup.getCopies().put(original, copy);
// PERF: Avoid synchronized enumerator as is concurrency bottleneck.
List<DatabaseMapping> mappings = getCloningMappings();
int size = mappings.size();
for (int index = 0; index < size; index++) {
mappings.get(index).buildCopy(copy, original, copyGroup);
}
if (copyGroup.shouldResetPrimaryKey() && (!(this.descriptor.isDescriptorTypeAggregate()))) {
// Do not reset if any of the keys is mapped through a 1-1, i.e. back reference id has already changed.
boolean hasOneToOne = false;
List<DatabaseMapping> primaryKeyMappings = getPrimaryKeyMappings();
size = primaryKeyMappings.size();
for (int index = 0; index < size; index++) {
if (primaryKeyMappings.get(index).isOneToOneMapping()) {
hasOneToOne = true;
}
}
if (!hasOneToOne) {
for (int index = 0; index < size; index++) {
DatabaseMapping mapping = primaryKeyMappings.get(index);
// Only null out direct mappings, as others will be nulled in the respective objects.
if (mapping.isAbstractColumnMapping()) {
Object nullValue = ((AbstractColumnMapping) mapping).getObjectValue(null, copyGroup.getSession());
mapping.setAttributeValueInObject(copy, nullValue);
} else if (mapping.isTransformationMapping()) {
mapping.setAttributeValueInObject(copy, null);
}
}
}
}
// PERF: Avoid events if no listeners.
if (this.descriptor.getEventManager().hasAnyEventListeners()) {
org.eclipse.persistence.descriptors.DescriptorEvent event = new org.eclipse.persistence.descriptors.DescriptorEvent(copy);
event.setSession(copyGroup.getSession());
event.setOriginalObject(original);
event.setEventCode(DescriptorEventManager.PostCloneEvent);
this.descriptor.getEventManager().executeEvent(event);
}
}
return copy;
}
Aggregations