cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Meeks, Andrew" <andrew.me...@vt.edu>
Subject RE: Cayenne 4.1 DataRow and objEntity with java.lang.Boolean
Date Thu, 07 Dec 2017 01:58:33 GMT
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:andrus@objectstyle.org] 
Sent: Wednesday, December 06, 2017 4:23 PM
To: user@cayenne.apache.org
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 <andrew.meeks@vt.edu> 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
> 


Mime
View raw message