Hi Craig,
I did some more research:
when I call
newexpensesentry.getToProjects().getName()
then somewhere in the framework the following method is called:
protected Object readProperty(String propName) {
if (persistenceState == PersistenceState.HOLLOW) {
dataContext.refetchObject(objectId);
}
return readPropertyDirectly(propName);
}
dataContext.refetchObject(objectId) returns actually a perfect Projects
object, with correct props HashMap,
public Object readPropertyDirectly(String propName) {
return props.get(propName);
}
but then : props is an empty HashMap
now I have to go to sleep its 2oclock in the morning
thanks for your help so far, think were gonna get this one.
greetings martin
Craig Miskell wrote:
> Glad to enlighten you regarding Hollow objects. This is a very odd
> situation. It still looks to me like you're getting a hollow object
> that's not getting filled in correctly, but I have no idea why! :-)
>
> You've obviously got DEBUG logging turned on (you say you see the
> objects are updated and inserted properly). All I can suggest is that
> you add your own logging statements at critical points: before/after
> commits or anything else that might cause DB access, and specifically
> right before you start accessing the Project properties that are
> returning null (i.e. right before we'd expect a database access to fetch
> the Project in question).
>
> Then run it and check the output. If nothing jumps out at you, e-mail
> it to me and we'll see what we can make of it together.
>
> We'll figure this out eventually,
>
> Craig
>
> On Fri, 2002-12-13 at 10:08, martin ruff wrote:
>
>>Hi Craig,
>
>
>>Oh thanks now I learned about "hollow" state
>>I get the properties by the generated accessor methods:
>>where newexpensesentry is the one after I inserted the values into the
>>db and then got this one by running a new query
>>String projectname = newexpensesentry.getToProjects().getName();
>>which returns me null:
>>String expenstype = newexpensesentry.getToExpensetype().getExpensetype();
>>which returns me the expensetype, this works, and I set the ExpenseType
>>exact the same way as the Project:
>>((Expensetypes)theDataContext.registeredObject(new
>> >> ObjectId(Expensetypes.class, "id",new Integer(1)))));
>>If I do this with a new DataContext (not the same as I used to save the
>>object) then everything works fine.
>>Now I found out that i have the same behaviour regardless of if I create
>>a new Expenses object and register it with the DataContext, fill set its
>>properties and save it, or if I edit an existing one and the get the
>>object back by a new SelectQuery, and again with a new DataContext it works
>>
>>her is the code with which I take n Expenses from a struts ActionFormBean
>>the code does the following: it checks if it has to create a new
>>Expenses object or edit an existing and the fills the values from the
>>form, the caller of thes form then calls:
>>theDataContext.commitChanges(Level.WARN);
>>this works fine in the console window if my IDE (eclipse, this one's
>>cool :-))) I can see that objects are updated and inserted according the
>>data passed from the form
>>
>> public static void populateExpenses(ExpensesDataForm expensesdataform,
>>DataContext theDataContext)
>> {
>> List expensesBOlist = expensesdataform.getExpensesBOsList();
>> int sizebefore = expensesBOlist.size();
>> for(int i = 0; i < expensesBOlist.size(); i++)
>> {
>> ExpensesBO theexpensesfromForm = (ExpensesBO)expensesBOlist.get(i);
>> Expenses origexpenses = null;
>> if(ApplicationConstants.NEWEXPENSES.equals(theexpensesfromForm.getID()))
>> {
>> if(!ApplicationConstants.NEWPROJECT.equals(new
>>Integer(theexpensesfromForm.getSelectedProject())))
>> {
>> origexpenses =
>>(Expenses)theDataContext.createAndRegisterNewObject("Expenses");
>> origexpenses.setInvoiced(new
>>BigDecimal(ApplicationConstants.ISNOTINVOICED));
>> }
>> }
>> else
>> {
>> origexpenses = theexpensesfromForm.getTheExpense();
>> }
>> if(origexpenses != null)
>> {
>>
>>origexpenses.setAmount(getBigDecimalFromString(theexpensesfromForm.getAmount()));
>> origexpenses.setExpensedate(new java.sql.Date(
>>DateFormatter.stringToDate_DDMMYYYY(theexpensesfromForm.getExpenseDate()).getTime()));
>>
>>origexpenses.setToEmployees(EmployeeService.findEmployeeByID(theDataContext,
>>new Integer(expensesdataform.getUserWhoWantsToRapport())));
>>
>>origexpenses.setToExpensetype(ExpenseTypesService.findExpenseTypesByID(theDataContext,
>>new Integer(theexpensesfromForm.getSelectedExpenseType())));
>>
>>origexpenses.setToProjects(ProjectsService.findProjectsByID(theDataContext,
>>new Integer(theexpensesfromForm.getSelectedProject())));
>>//theexpensesfromForm.getSelectedProject() returns me the correct
>>//projectID of an existing project in DB, checked this in debugger
>>origexpenses.setHours(getBigDecimalFromString(theexpensesfromForm.getHours()));
>> origexpenses.setInvoicable( new BigDecimal(
>>theexpensesfromForm.getInvoicable() ? ApplicationConstants.ISINVOICABLE
>>: ApplicationConstants.ISNOTINVOICABLE));
>> origexpenses.setNotice(theexpensesfromForm.getNotice());
>>
>>origexpenses.setNumberofkm(getBigDecimalFromString(theexpensesfromForm.getNumberofkm()));
>>
>>origexpenses.setToEmployeesResponsible(EmployeeService.findEmployeeByID(theDataContext,
>>new Integer(expensesdataform.getUserWhoWantsToRapport())));
>> //todo herausfinden, wer verantwortlich ist
>> //origexpenses.setResponsible()
>> }
>> }
>> }
>>
>>
>>the findXXXbyID look all the same, here one as an example:
>> public static Projects findProjectsByID(DataContext theDataContext,
>>Integer projectsID)
>> {
>> return (Projects)theDataContext.registeredObject(new
>>ObjectId(Projects.class, "ID",projectsID.intValue()));
>> }
>>
>>here's the code whith which I get a list of Expenses (if I set the same
>>time range as for the above inserted Expenses, which I do for testing)
>>then I get the same objects as I inserted or updated above:
>> public static List getExpenses4EmployeeInTimeFrame(DataContext
>>theDataContext, Date beginDate, Date endDate, Employees theemployee)
>> {
>>
>> Expression employeeidexpr = ExpressionFactory.binaryPathExp(
>> Expression.EQUAL_TO,
>> "ToEmployees",
>> theemployee);
>>
>> Expression begindateexpr = ExpressionFactory. binaryPathExp(
>> Expression.GREATER_THAN_EQUAL_TO,
>> "expensedate",
>> beginDate);
>> Expression enddateexpr = ExpressionFactory.binaryPathExp(
>> Expression.LESS_THAN_EQUAL_TO,
>> "expensedate",
>> endDate);
>>
>> employeeidexpr = employeeidexpr.andExp(begindateexpr).andExp(enddateexpr);
>> SelectQuery query = new SelectQuery("Expenses", employeeidexpr);
>> query.addOrdering("expensedate", true);
>> return theDataContext.performQuery(query);
>>
>>This is the code which is running, thanks again for your time and have a
>>nice day, greetings from cold switzerland
>>martin
>>
>> >(If not, then that would be *very* interesting and maybe indicative of >a
>> >problem).
>> >
>> >As to what the real problem may be:
>> >Assuming that you are setting the toProjects in the same way as below
>> >(obtaining it from theDataContext.registeredObject, by primary key),
>> >then the object returned will be "hollow". The object (Project) will
>> >not be fetched from the db until it's properties are read. So, the big
>> >question is how are you reading it's properties? If you are using
>> >readPropertyDirectly, then you are seeing expected behaviour....
>> >readPropertyDirectly will not automatically fetch a HOLLOW object. You
>> >have to use either readProperty (defined on CayenneDataObject rather
>> >than DataObject), or the standard accessor methods (getTitle() etc.)
>> >
>> >If you are using the standard accessor methods, as generated by >Cayenne,
>> >then something else strange is occuring. More code would help, if
>> >you're permitted to send it (e-mail me privately if public distribution
>> >is an issue).
>>
>> >Hope this (or something else) helps,
>> >Craig Miskell
>>
>> >On Fri, 2002-12-13 at 07:03, martin ruff wrote:
>> >> Hi I've got the following table
>> >> CREATE TABLE expenses(
>> >> id serial NOT NULL PRIMARY KEY,
>> >> fk_employeeid int4 NOT NULL,
>> >> fk_projectid int4 NOT NULL,
>> >> expensedate date NOT NULL,
>> >> fk_expensetype int4 NOT NULL,
>> >> notice varchar(2000) NOT NULL,
>> >> numberofkm numeric,
>> >> hours numeric,
>> >> amount numeric,
>> >> invoicable numeric(1),
>> >> invoiced numeric(1),
>> >> responsible int4 NOT NULL,
>> >> FOREIGN KEY (fk_employeeid) REFERENCES employees (id),
>> >> FOREIGN KEY (fk_projectid) REFERENCES projects (id),
>> >> FOREIGN KEY (fk_expensetype) REFERENCES expensetypes (id),
>> >> FOREIGN KEY (responsible) REFERENCES employees (id));
>> >>
>> >> What I do:
>> >> I create a new Expenses object and register it with DataContext:
>> >> Expenses newexpensesentry =
>> >> (Expenses)theDataContext.createAndRegisterNewObject("Expenses");
>> >> then I fill all the values into that object I've defined relations >for
>> >> the fk_.. references
>> >>
>> >> <obj-relationship name="ToEmployees" source="Expenses"
>> >> target="Employees" toMany="false">
>> >> <db-relationship-ref source="expenses" target="employees"
>> >> name="ToEmployees"/>
>> >> </obj-relationship>
>> >> <obj-relationship name="ToEmployeesResponsible" source="Expenses"
>> >> target="Employees" toMany="false">
>> >> <db-relationship-ref source="expenses" target="employees"
>> >> name="ToEmployeesResponsible"/>
>> >> </obj-relationship>
>> >> <obj-relationship name="ToExpensetype" source="Expenses"
>> >> target="Expensetypes" toMany="false">
>> >> <db-relationship-ref source="expenses" target="expensetypes"
>> >> name="ToExpensetype"/>
>> >> </obj-relationship>
>> >> <obj-relationship name="ToProjects" source="Expenses" >target="Projects"
>> >> toMany="false">
>> >> <db-relationship-ref source="expenses" target="projects"
>> >> name="ToProjects"/>
>> >> </obj-relationship>
>> >>
>> >> then I set the refenrenced objects i.e.
>> >>
>> >>newexpensesentry.ToExpensetype((Expensetypes)theDataContext.registeredObject(new
>> >> ObjectId(Expensetypes.class, "id",new Integer(1)))));
>> >> I have the find the referenced object via it's primary key because
>> >>from
>> >> a web-interface I only get the primary key for the referenced object
>> >>and
>> >> not the object itself
>> >> I do this for all the referenced objects:
>> >> then I call theDataContext.commitChanges(Level.WARN);
>> >> everything works fine, the problem comes now:
>> >> If I get a list of expenses in a timerange (the Expense object
>> >>inserted
>> >> above is under the returned objects), then the newly created Expense
>> >> objects I get in return from my query has an empty (properties are
>> >> empty) Projects (relation ToProjects) objects related to it. The
>> >>strange
>> >> thing is, that the ExpenseType object that I get over the relation
>> >> ToExpensetype is ok.
>> >> If I create a NEW DataContext and rerun the query, again, everything
>> >>is
>> >> ok, also the Projects object thas had empty properties before.
>> >> If I use THE SAME DataContext to insert a new Espense object and the
>> >>run
>> >> the query I get problems as described above.
>> >> Has anyone a idea what the problem could be here?
>> >> thanks in advance
>> >> martin
>> >>
>>
>>
>
This archive was generated by hypermail 2.0.0 : Thu Dec 12 2002 - 19:32:54 EST