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 - 16:30:05 EST