google-app-engine


Bi-directional one-to-many relationship in google app engine using JPA


I want to create entity group in GAE Datastore such that one city have contain multiple suburbans. Following is my code :-
//city.java
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Entity
public class City
{
#Id
private String name;
#OneToMany(mappedBy="city", cascade=CascadeType.ALL)
private Suburban[] suburbans;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Suburban[] getSuburbans()
{
return suburbans;
}
public void setSuburbans(Suburban[] suburbans)
{
this.suburbans = suburbans;
}
}
//suburban.java
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Entity
public class Suburban
{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Key id;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private City city;
public City getCity()
{
return city;
}
public void setCity(City city)
{
this.city = city;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Key getId()
{
return id;
}
}
I am auto-generating cityendpoint class using google-plugin for eclipse option "Generate Cloud Endpoint Class".
//CityEndpoint.java
#Api(name = "cityendpoint", namespace = #ApiNamespace(ownerDomain = "zestbuds.com", ownerName = "zestbuds.com", packagePath = "android"))
public class CityEndpoint
{
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listCity")
public CollectionResponse<City> listCity(#Nullable #Named("cursor") String cursorString, #Nullable #Named("limit") Integer limit)
{
EntityManager mgr = null;
Cursor cursor = null;
List<City> execute = null;
try
{
mgr = getEntityManager();
Query query = mgr.createQuery("select from City as City");
if (cursorString != null && cursorString != "")
{
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null)
{
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<City>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (City obj : execute)
;
} finally
{
mgr.close();
}
return CollectionResponse.<City> builder().setItems(execute).setNextPageToken(cursorString).build();
}
/**
* This method gets the entity having primary key id. It uses HTTP GET method.
*
* #param id the primary key of the java bean.
* #return The entity with primary key id.
*/
#ApiMethod(name = "getCity")
public City getCity(#Named("id") String id)
{
EntityManager mgr = getEntityManager();
City city = null;
try
{
city = mgr.find(City.class, id);
} finally
{
mgr.close();
}
return city;
}
/**
* This inserts a new entity into App Engine datastore. If the entity already
* exists in the datastore, an exception is thrown.
* It uses HTTP POST method.
*
* #param city the entity to be inserted.
* #return The inserted entity.
*/
#ApiMethod(name = "insertCity")
public City insertCity(City city)
{
EntityManager mgr = getEntityManager();
try
{
if (containsCity(city))
{
throw new EntityExistsException("Object already exists");
}
mgr.persist(city);
} finally
{
mgr.close();
}
return city;
}
/**
* This method is used for updating an existing entity. If the entity does not
* exist in the datastore, an exception is thrown.
* It uses HTTP PUT method.
*
* #param city the entity to be updated.
* #return The updated entity.
*/
#ApiMethod(name = "updateCity")
public City updateCity(City city)
{
EntityManager mgr = getEntityManager();
try
{
if (!containsCity(city))
{
throw new EntityNotFoundException("Object does not exist");
}
mgr.persist(city);
} finally
{
mgr.close();
}
return city;
}
/**
* This method removes the entity with primary key id.
* It uses HTTP DELETE method.
*
* #param id the primary key of the entity to be deleted.
*/
#ApiMethod(name = "removeCity")
public void removeCity(#Named("id") String id)
{
EntityManager mgr = getEntityManager();
try
{
City city = mgr.find(City.class, id);
mgr.remove(city);
} finally
{
mgr.close();
}
}
private boolean containsCity(City city)
{
EntityManager mgr = getEntityManager();
boolean contains = true;
try
{
City item = mgr.find(City.class, city.getName());
if (item == null)
{
contains = false;
}
} finally
{
mgr.close();
}
return contains;
}
private static EntityManager getEntityManager()
{
return EMF.get().createEntityManager();
}
}
Initally, I was not using #JsonIdentityInfo, and hence I was getting java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError). After reading thread, I recognized my error is due to jackson.
After reading Thread, I decided to use #JsonIdentityInfo. Now I am getting
java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: You have just attempted to access field "suburbans" yet this field was not detached when you detached the object. Either dont access this field, or detach it when detaching the object. (through reference chain: com.google.api.server.spi.response.CollectionResponse["items"]->com.google.appengine.datanucleus.query.StreamingQueryResult[0]->com.zestbuds.android.City["suburbans"])
why am I getting suburban is not detached, even though I am using Cascade.ALL?
Finally solved issue.
There is no need of using #JsonIdentityInfo . I just needed to remove getter and setter method for class member having #ManyToOne annotation(In my case, I removed getCity() and setCity()).
Here is the example provided by datanucleus for bidirectional one-to-many mapping.

Related Links

Issue with using the Google Datastore query console
How can I run `gcloud preview app setup-managed-vms` without this error?
Appengine unit test fail with Objectify - No Class registered
What is the name of the database or table?
Google Apps Domain Authentication with Google App Engine - Too many redirects
can I combine NDB and mysqldb in one app on google cloud platform
Logging in a Google Cloud Endpoint
Appengine Maven Plugin - Endpoints Goal - Enable filtering on .discovery files
authentication request once for both side
How do I remove my reported issue from google code bug tracking?
Can I use Goroutines in Google App Engine?
Google App Engine: Caching a 30 mb object
How to store image location in google app engine (Java)
Get a public link after uploading to Google Cloud Storage using JavaScript Client
Create a form into Polymer - (Google App Engine & Python)
Mass rename objects on Google Cloud Storage

Categories

HOME
shell
xml
grok
delphi-7
amp-html
redux-form
battery
serialization
mstest
sh
devise
vscode-extensions
seo
carousel
rds
x264
sendgrid-api-v3
startup
windows-ce
mxgraph
automatic-ref-counting
scrolltop
gruntfile
internationalization
android-7.0-nougat
r-mice
php-mysqlidb
google-api-client
google-cloud-print
stackexchange
amazon-quicksight
progress-bar
iis-express
mobx
anki
utorrent
jmockit
memory-address
gnat-gps
sendbird
hibernate-search
swagger-php
reason
playframework-2.1
chef-solo
glm-math
wc
stylecop
plan-9
libgphoto2
quicktime
google-photos
rmongo
microstation
google-cloud-console
rspec2
mapinfo
firebase-security
lean
observablecollection
lz77
thread-sleep
nio2
aspen
fiware-monitoring
include-guards
canalyzer
typemock
android-broadcast
qtwebengine
infosphere-spl
mintty
twitter-bootstrap-rails
drupal-nodes
visual-studio-express
beaker-testing
observium
time.h
failing-tests
infobright
mbeans
inline-formset
socketserver
timertask
instantiationexception
django-piston
skype4java
web-application-project
wysiwym
idatareader

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile