Hi Craig,
I FOUND the mistake !!!!
it was a proplem in the datamap:
all other object entities have a primary key definition:
(I got those by reverse engineering the database)
id integer PK mandatory maxlength 4
projects had:
id numeric PK mandatory
now I changed it to:
id integer PK mandatory maxlength 4
and now it works:
(Projects)theDataContext.registeredObject(new ObjectId(Projects.class,
"id",projectsID.intValue()));
now returns me a correct Projects object
one question:
maxlength, does this mean 4 digits?
and if so, how is this enforced?
cause I have entries with id's > 9999 ?
for example in the auto_pk_support table for reportingdates the next id
is 10100
thanks again for your time and help
martin
Craig Miskell wrote:
> Truly odd.
>
> When you say "with correct props HashMap", does that mean that the
> Projects has data at some stage, but not later on? My current guess is
> that the problem is some different section of code to what you've posted
> so far, possibly some unexpected side-effect of some call or other.
>
> I just checked, and the only place where the props hashmap is set is at
> object init time, and during deserialization. So unless you're
> deserializing and it's all going bad (unusual, because it deserializes
> into the HOLLOW state so it should fill itself in later), then I don't
> know what's happening.
>
> Are you setting the persistence state anywhere? Calling any other methods
> in DataContext?
>
> Craig
>
> On Fri, 13 Dec 2002, martin ruff wrote:
>
>
>>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 : Fri Dec 13 2002 - 06:35:32 EST