/** * Instantiates a new object and registers it with this context. Object class is determined from * the mapped entity. Object class must have a default constructor. * * <p><i>Note: in most cases {@link #newObject(Class)} method should be used, however this method * is helpful when generic persistent classes are used.</i> * * @since 3.0 */ public Persistent newObject(String entityName) { ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entityName); if (descriptor == null) { throw new IllegalArgumentException("Invalid entity name: " + entityName); } Persistent object; try { object = (Persistent) descriptor.createObject(); } catch (Exception ex) { throw new CayenneRuntimeException("Error instantiating object.", ex); } // this will initialize to-many lists descriptor.injectValueHolders(object); ObjectId id = new ObjectId(entityName); // note that the order of initialization of persistence artifacts below // is // important - do not change it lightly object.setObjectId(id); injectInitialValue(object); return object; }
/** * An internal version of {@link #localObject(Object)} that operates on ObjectId instead of * Persistent, and wouldn't attempt to look up an object in the parent channel. * * @since 3.1 */ Persistent findOrCreateObject(ObjectId id) { if (id == null) { throw new IllegalArgumentException("Null ObjectId"); } // have to synchronize almost the entire method to prevent multiple // threads from // messing up dataobjects per CAY-845. Originally only parts of "else" // were // synchronized, but we had to expand the lock scope to ensure // consistent // behavior. synchronized (getGraphManager()) { Persistent cachedObject = (Persistent) getGraphManager().getNode(id); // return an existing object if (cachedObject != null) { int state = cachedObject.getPersistenceState(); // TODO: Andrus, 1/24/2006 implement smart merge for modified // objects... if (state != PersistenceState.MODIFIED && state != PersistenceState.DELETED) { ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(id.getEntityName()); descriptor.injectValueHolders(cachedObject); } return cachedObject; } // create and register a hollow object ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(id.getEntityName()); Persistent localObject = (Persistent) descriptor.createObject(); localObject.setObjectContext(this); localObject.setObjectId(id); getGraphManager().registerNode(id, localObject); localObject.setPersistenceState(PersistenceState.HOLLOW); return localObject; } }
/** * Registers a transient object with the context, recursively registering all transient persistent * objects attached to this object via relationships. * * <p><i>Note that since 3.0 this method takes Object as an argument instead of a {@link * DataObject}.</i> * * @param object new object that needs to be made persistent. */ @Override public void registerNewObject(Object object) { if (object == null) { throw new NullPointerException("Can't register null object."); } ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object); if (entity == null) { throw new IllegalArgumentException( "Can't find ObjEntity for Persistent class: " + object.getClass().getName() + ", class is likely not mapped."); } final Persistent persistent = (Persistent) object; // sanity check - maybe already registered if (persistent.getObjectId() != null) { if (persistent.getObjectContext() == this) { // already registered, just ignore return; } else if (persistent.getObjectContext() != null) { throw new IllegalStateException( "Persistent is already registered with another DataContext. " + "Try using 'localObjects()' instead."); } } else { persistent.setObjectId(new ObjectId(entity.getName())); } ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName()); if (descriptor == null) { throw new IllegalArgumentException("Invalid entity name: " + entity.getName()); } injectInitialValue(object); // now we need to find all arc changes, inject missing value holders and // pull in // all transient connected objects descriptor.visitProperties( new PropertyVisitor() { public boolean visitToMany(ToManyProperty property) { property.injectValueHolder(persistent); if (!property.isFault(persistent)) { Object value = property.readProperty(persistent); Collection<Map.Entry> collection = (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value; Iterator<Map.Entry> it = collection.iterator(); while (it.hasNext()) { Object target = it.next(); if (target instanceof Persistent) { Persistent targetDO = (Persistent) target; // make sure it is registered registerNewObject(targetDO); getObjectStore() .arcCreated( persistent.getObjectId(), targetDO.getObjectId(), property.getName()); } } } return true; } public boolean visitToOne(ToOneProperty property) { Object target = property.readPropertyDirectly(persistent); if (target instanceof Persistent) { Persistent targetDO = (Persistent) target; // make sure it is registered registerNewObject(targetDO); getObjectStore() .arcCreated(persistent.getObjectId(), targetDO.getObjectId(), property.getName()); } return true; } public boolean visitAttribute(AttributeProperty property) { return true; } }); }