Override Comparable interface for GAE property? - google-app-engine

I'm not sure if this is possible at all, but is there a way to override the Comparable used by a Google App Engine property when used in a query? For example, there is a property type PhoneNumber (basically a String) that in the docs has a method:
public int compareTo(PhoneNumber o)
Specified by:
compareTo in interface java.lang.Comparable<PhoneNumber>
The exact workings of how it compares I haven't been able to find. Is there a way to override that Comparable so that it compares it in a way I choose?
Thanks

No. But you can sort any collection any way you want. Since you tagged this with objectify:
#Entity
public class Thing {
private static final Comparator<PhoneNumber> SPECIAL_COMPARATOR = // make one
// ... id, etc
SortedSet<PhoneNumber> phoneNumbers = new TreeSet<>(SPECIAL_COMPARATOR);
}
This won't help you if you need the phone numbers indexed in a particular way (although collection property index sorting would be very strange anyways). If you have a single indexed phone number property and you want to control index ordering, you need to create your own PhoneNumber that translates to a correctly-sorted String representation. You'll need to register your own PhoneNumberTranslatorFactory with Objectify. This is not hard; look at the source code for examples.

Related

How to compare two objects by value

I need to compare two objects of the same class by value to see whether all their values match or not.
For background this is so I can compare before and after values of a wpf datagrid row
Say the objects are both House class with properties of name, street, town (all strings).
So the class would be
public class House
public property name as string
public property street as string
public property town as string
end class
Should I
1) override equals in the House class and in it check name=name, street=street, town=town
2) make the House class implement IComparable and create a compare function that implements it, checking each property as 1
3) there's a better way you know that I dont!
I'd appreciate an example based on this scenario if possible.
Many thanks
You should be using Option 1 : Overriding the Equals method.
Why ?
Because the Equals() method is supposed to be used when you want to compare if two objects are the same.
So what's the use of IComparabe ?
IComparable interface has a different purpose. Its goal is to check if an object is supposed to go before or after another object. Therefore this is used by sorting methods.
You can implement the IComparable interface and check if two object's CompareTo() method return 0. However it only means that they are supposed to get the same ranking, not that they are equals...
Is there another approach ?
There are plenty differents ways of doing what you want to do. But since there is a simple and elegant method that is here, let's use that one. The main difficulty in programming an application is to find the tools that are already here to do what you want...
So how to Override the Equals() method ?
This link to MSDN explains how to override the Equals method
In short (I'm just copy/pasting from MSDN and removing error checking for clarity here) :
Public Class Point
Protected x As Integer
Protected y As Integer
Public Sub New (xValue As Integer, yValue As Integer)
Me.x = xValue
Me.y = yValue
End Sub
Public Overrides Overloads Function Equals(obj As Object) As Boolean
Dim p As Point = CType(obj, Point)
Return Me.x = p.x And Me.y = p.y
End Function
End Class
Do not use this straight ahead and read article first, as you must do some error checking in the Equals, because it could throw some exception when converting Object to Point...

JPA map entity with array datatype

I have a table which contains a column of type: integer[]
I'm trying to map my entity to this table and I've tried the following suggestion of:
#ElementCollection
private ArrayList<Integer> col;
public MyEntity() {
col = new ArrayList<>();
}
However I get the following error: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements
Not sure how to get around this. I'm open to changing the entity's datatype, but I would prefer not to move this property into its own table/entity. Is there another solution? Thanks.
The field must be of type List<Integer>, not ArrayList<Integer>.
The JPA engine must be able to use its own List implementation, used for lazy-loading, dirty checking, etc.
It's a good idea in general to program on interfaces rather than implementations, and it's a requirement to do it in JPA entities.

Queries with Objectify: UmbrellaException

I am using Objectify to manage GAE Datastore for my GWT app. The problem is that I am not using queries properly and I get UmbrellaExceptions as per below:
Caused by: java.lang.RuntimeException: Server Error: java.lang.String cannot be cast to java.lang.Number
at com.google.web.bindery.requestfactory.shared.Receiver.onFailure(Receiver.java:44)
Say that I have a class Box with a unique field String id. I want to get the Box object whose id == "cHVQP6zZiUjM"
This is how I do it now:
public Box getBox(String boxId)
{
Objectify ofy = ObjectifyService.begin();
Query<Box> q=ofy.query(Box.class).filter("id",boxId);
Box targetBox = q.get();
return targetBox;
}
#Entity
public class Box extends DatastoreObject{
private String id;
private String title;
}
I tried doing this with ofy.load() but that method is not defined in my class Objectify (I don't know why).
Your key is encoded. Try using:
Box targetBox = ofy.get(Box.class, KeyFactory.stringToKey(boxId));
To decode your key.
The short answer: You are missing the #Id annotation in your entity.
The long answer: Id fields are special in the datastore. The id is not a real property, but rather a part of the Key that identifies the entity. You can't really filter on id fields, but you can filter on a special field called __key__. Objectify is somewhat clever about letting you filter by the id field and converting this to a __key__ filter under the covers, but it can't do it if you don't annotate the entity properly!
Actually I'm a little confused because Objectify shouldn't let you register the entity without an #Id field.
By the way, there are two sections of the documentation: Objectify4 (release coming soon) and Objectify3. Since you're using Ofy3, there is no load() method.
Another thing: Get-by-key operations are strongly preferred to queries when the operations are equivalent (as they are in your example).

Dapper Correct Object / Aggregate Mapping

I have recently started evaluating Dapper as a potential replacement for EF, since I was not too pleased with the SQL that was being generated and wanted more control over it. I have a question regarding mapping a complex object in my domain model. Let's say I have an object called Provider, Provider can contain several properties of type IEnumerable that should only be accessed by going through the parent provider object (i.e. aggregate root). I have seen similar posts that have explained using the QueryMultiple and a Map extension method but was wondering how if I wanted to write a method that would bring back the entire object graph eager loaded, if Dapper would be able to do this in one fell swoop or if it needed to be done piece-meal. As an example lets say that my object looked something like the following:
public AggregateRoot
{
public int Id {get;set;}
...//simple properties
public IEnumerable<Foo> Foos
public IEnumerable<Bar> Bars
public IEnumerable<FooBar> FooBars
public SomeOtherEntity Entity
...
}
Is there a straightforward way of populating the entire object graph using Dapper?
I have a similar situation. I made my sql return flat, so that all the sub objects come back. Then I use the Query<> to map the full set. I'm not sure how big your sets are.
So something like this:
var cnn = sqlconnection();
var results = cnn.Query<AggregateRoot,Foo,Bars,FooBar,someOtherEntity,AggregateRoot>("sqlsomething"
(ar,f,b,fb,soe)=>{
ar.Foo = f;
ar.Bars = b;
ar.FooBar = fb;
ar.someotherentity = soe;
return ar;
},.....,spliton:"").FirstOrDefault();
So the last object in the Query tag is the return object. For the SplitOn, you have to think of the return as a flat array that the mapping will run though. You would pick the first return value for each new object so that the new mapping would start there.
example:
select ID,fooid, foo1,foo2,BarName,barsomething,foobarid foobaritem1,foobaritem2 from blah
The spliton would be "ID,fooid,BarName,foobarid". As it ran over the return set, it will map the properties that it can find in each object.
I hope that this helps, and that your return set is not too big to return flat.

What is dbReferenceProperty?

In the python app engine docs, I see something called dbReferenceProperty. I can't understand what it is, or how it's used. I'm using the java interface to app engine, so I'm not sure if there's an equivalent.
I'm interested in it because it sounds like some sort of pseudo-join, where we can point a property of a class to some other object's value - something like if we had:
class User {
private String mPhotoUrl;
private String mPhone;
private String mState;
private String mCountry;
.. etc ..
}
class UserLite {
#ReferenceProperty User.mPhotoUrl;
private String mPhotoUrl;
}
then if we had to update a User object's mPhotoUrl value, the change would somehow propagate out to all UserLite instances referencing it, rather than having to update every UserLite object instance manually,
Thanks
A db.ReferenceProperty simply holds the key of another datastore entity, which is automatically fetched from the datastore when the property is used.
There's some additional magic where the entity that is referenced has access to a query for entities of type Foo that reference it in the special attribute foo_set.
The Java datastore API instead has owned relationships, which serve the same purpose.

Resources