Hi Ludo,

if "enableChangePerThread" is set true, your workaround should be valid.

The only drawback is the
> DescriptorRepository dr = manager.copyOfGlobalRepository();
call. If you have thousands of objects this method is costly (serialization of the DescriptorRepository instance).


Think to make it faster (but more complex) you can try to use a temporary DescriptorRepository instance with temp ClassDescriptor (not tested, only suggestion, does not work when using multiple joined table):

Seems to be complex, but should be faster than serialize the whole global DescriptorRepository on each method call.

public void update(Object target, String[] fieldsToUpdate)
{
DescriptorRepository temp = createTempRepositoryFor(
manager.getRepository().getDescriptorFor(target.getClass()), fieldsToUpdate);
manager.setDescriptor(temp);
PersistenceBroker broker = getBroker();
try
{
/*
now we can store the object to update
*/
//...
broker.beginTransaction();
broker.store(target);
broker.commitTransaction();
//... cleanup broker, exception handling
}
finally
{
manager.setDescriptor(null);
}
}


private DescriptorRepository createTempRepositoryFor(ClassDescriptor target, String[] fieldsToUpdate)
{
DescriptorRepository temp = new DescriptorRepository();
ClassDescriptor cld = new ClassDescriptor(temp);
temp.setClassDescriptor(cld);
// if an schema was used this method need more tweak to resolve table name
cld.setTableName(target.getFullTableName());
FieldDescriptor[] fields = getFieldsToUpdate(cld, fieldsToUpdate);
for(int i = 0; i < fields.length; i++)
{
FieldDescriptor field = fields[i];
cld.addFieldDescriptor(field);
}
return temp;
}



private FieldDescriptor[] getFieldsToUpdate(ClassDescriptor target, String[] fieldsToUpdate)
{
ArrayList result = new ArrayList();
FieldDescriptor[] fields = target.getFieldDescriptions();
for(int i = 0; i < fieldsToUpdate.length; i++)
{
String fieldName = fieldsToUpdate[i];
for(int k = 0; k < fields.length; k++)
{
FieldDescriptor field = fields[k];


if(field.getPersistentField().getName().equalsIgnoreCase(fieldName))
{
// make deep copy of used field
result.add(SerializationUtils.clone(field));
break;
}
}
}
if(fieldsToUpdate.length != result.size())
{
// throw exception, not all fields could be found
}
return (FieldDescriptor[]) result.toArray(new FieldDescriptor[result.size()]);
}


regards,
Armin


Ludovic Maitre (POP - Factory Part) wrote:

Hello,

I do this myself, updating only selected foreign keys or relationships (and fetching also). I give the code below, since i appreciate to have some feedback. This rely on modifying the meta datas at runtime, after having set enableChangePerThread (or something like this) to true in the initialization of OJB.
I anybody could say if i could remove the "i hope" from my commentary, i will appreciate.
Regards,
Ludo


This work and is implemented in a wrapper around pb api like this :
public synchronized Object store(Object o, String[] filter)
throws SQLException, DAOException {
String[] refs = getCurrentBean().getPersistentReferencesNames();
//first index: refs index, second index: 0: cascade store, 1: cascade delete
int[][] state = new int[refs.length][2];
ObjectReferenceDescriptor[] ords = new ObjectReferenceDescriptor[refs.length];
PBKey key = OJBHelper.getDefaultKey();
MetadataManager manager = OJBHelper.getManager();
DescriptorRepository dr = manager.copyOfGlobalRepository();
ClassDescriptor cld = dr.getDescriptorFor(currentBean);
Property p;
//create array of references and save state
for (int i = 0; i < refs.length; i++) {
ObjectReferenceDescriptor ord = cld
.getCollectionDescriptorByName(refs[i]);
if (ord == null)
ord = cld.getObjectReferenceDescriptorByName(refs[i]);
if (ord != null) {
ords[i] = ord;
p = getCurrentBean().getProperty(ord.getAttributeName());
state[i][0] = ord.getCascadingStore();
state[i][1] = ord.getCascadingDelete();
if (ArrayUtils.contains(filter, ord.getAttributeName())) {
if (p.getBean().isStatic()) { ord.setCascadingStore(ObjectReferenceDescriptor.CASCADE_LINK);


ord.setCascadingDelete(ObjectReferenceDescriptor.CASCADE_LINK);
} else {
ord.setCascadingStore(ObjectReferenceDescriptor.CASCADE_OBJECT);


ord.setCascadingDelete(ObjectReferenceDescriptor.CASCADE_OBJECT);

}
} else {
ord.setCascadingStore(ObjectReferenceDescriptor.CASCADE_NONE);
ord.setCascadingDelete(ObjectReferenceDescriptor.CASCADE_NONE);
}
//log.info(ord.getClassDescriptor().getRepository().getDescriptorFor(ord.getItemClassName()));


           } else
               log.error("No reference descriptor found for " + refs[i]);
       }
       manager.setDescriptor(dr);
       PersistenceBroker broker = PersistenceBrokerFactory
               .createPersistenceBroker(key);

       broker.beginTransaction();
       broker.store(o);
       broker.commitTransaction();

       if (broker != null)
           broker.close();

       //restore old state (i hope)
       for (int i = 0; i < ords.length; i++) {
           //if (ords[i] != null) {
               ords[i].setCascadingStore(state[i][0]);
               ords[i].setCascadingDelete(state[i][1]);
           //}
       }
       return o;
   }


Thomas Franke wrote:

Parvathi Rajaraman wrote:

Does anyone know how to update selected columns of a table using OJB. We are
using the PersistanceBroker API's store method that will either insert or
update all the columns based on the primary key value. But I want to update
only a few columns for multiple records based on a key value. Is this
possible??


No, at the time all columns will be updatet. Or you must write a special class with the columns you want to update.



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to