Thank you, yes, I am using SQLSelect but I had not made use of the #result directive. I shall do so!
Andrew -----Original Message----- From: Andrus Adamchik [mailto:[email protected]] Sent: Wednesday, December 06, 2017 4:23 PM To: [email protected] Subject: Re: Cayenne 4.1 DataRow and objEntity with java.lang.Boolean Hi Andrew, What is the origin of the DataRows? If they come from a SQLSelect/SQLTemplate query, there's a way to control value types with #result directive [1]. This will fix the issue in 4.1, and is arguably the best approach even in 4.0, as loading values of incorrect type to a DataObject via a generic API only defers a ClassCastException, not prevents it entirely. Cheers, Andrus [1] https://cayenne.apache.org/docs/4.0/cayenne-guide/queries.html#sqltemplate > On Dec 5, 2017, at 11:00 AM, Meeks, Andrew <[email protected]> wrote: > > I have recently migrated from 4.0 to 4.1. I have a few instances where I > perform a query and then I create an instance of my entity from the resulting > DataRow. These object entities have both Integer and Boolean fields. > DataRow has always cast these fields as BigDecimal. > > In 4.0 the DataContext.objectFromDataRow handled these fields, evidently > because CayenneDataObject could put BigDecimal into the values map of > <String, Object>. > > In 4.1 it appears as though each entity implements its own > writePropertyDirectly which puts the object into a typed field of that > entity. The objectFromDataRow fails because of the cast exception from > BigDecimal to Boolean or BigDecimal to Integer. So these fields evidently > need to be converted to correct types before being set on the entity. > > My workaround is to write a utility method that cleans up the DataRow before > I hand it to objectFromDataRow. The utility method looks for any attributes > that are BigDecimal on the DataRow, then for the same field name in the > entity, it looks for the desired type. Then it does an appropriate > conversion from BigDecimal. > > public static void cleanUpDataRow(DataContext dContext, Class clazz, > DataRow dataRow) { > ObjEntity entity = > dContext.getEntityResolver().getObjEntity(clazz); > Collection<ObjAttribute> entityAttributes = > entity.getAttributes(); > for(ObjAttribute attribute : entityAttributes) { > String attributeClass = attribute.getType(); > if(dataRow.get(attribute.getDbAttributeName()) != null > && > > dataRow.get(attribute.getDbAttributeName()).getClass().getTypeName().equals("java.math.BigDecimal")) > { > if(attributeClass.equals("java.lang.Boolean")) { > > dataRow.put(attribute.getDbAttributeName(), > (dataRow.get(attribute.getDbAttributeName()).equals(BigDecimal.valueOf(1)))); > } else > if(attributeClass.equals("java.lang.Integer")) { > > dataRow.put(attribute.getDbAttributeName(), > ((BigDecimal)dataRow.get(attribute.getDbAttributeName())).intValue()); > } > } > } > } > > Usage: > > ... > CayennePatch.cleanUpDataRow(dContext, ROrganizationalChart.class, > dataRow); ROrganizationalChart fetchedChart = > dataContext.objectFromDataRow(ROrganizationalChart.class, dataRow); ... > > How can I use DataRows in 4.1 with objectFromDataRow without using a custom > method? > Thank you! > Andrew >
