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
> 

Reply via email to