Sounds like exactly what i was looking for! Cant wait to try it
thanks, erik On 13 Jan., 18:28, Jeff Schnitzer <j...@infohazard.org> wrote: > http://code.google.com/p/objectify-appengine/ > > I probably should have called this project "Goldilocks", because it's > a little bit how I feel. Despite being a longtime Hibernate user > (since the 1.0 days), the JDO/JPA abstraction just doesn't make me > happy on appengine - it's too big, too complicated, and too far > removed from the nature of the beast. The low-level API has an > elegant simplicity, but it lacks type safety. I tried the > alternatives - Siena, Twig, SimpleDS, and Slim3. There are good > things I can say about these projects but none were "just right" for > me. > > So, in time-honored tradition, I wrote my own and now I'm offering it > to the world. Here is what "just right" means to me. Maybe it's just > right for you too: > > * An interface that reflects the four fundamental datastore > operations - get, put, delete, query - including their batch variants. > > * Persisting real typed POJO classes - no detaching, no lifecycle, > serialize at will. > > * Keys in Objectify are generified and typed. Instead of Key you use > OKey<MyEntity>. This generic typing extends to OQuery<MyEntity> and > OPreparedQuery<MyEntity>. > > * Because Kind ~= POJO Class, Key should not be used for an object's > id. The object's id and its (optional) parent plus the class is > complete; an entity that has a Key identifier contains a redundant > (and potentially inaccurate) kind. Nevertheless, a Key is necessary > for loading entities or referencing entities, and forms a fundamental > part of the API. This dichotomy is something I don't feel had been > done right yet. > > * Queries are modeled after the human-friendly GAE/Python Query > class: query.filter("field >", 123).sort("-field"). You can filter > and sort on id fields almost as if they are normal properties. > > * Transactional behavior is contained within the Objectify interface > (analogous to DatastoreService) instance rather than a thread local. > You can easily have several transactions (or nontransactional > sessions) running concurrently. > > * You can use your entities in GWT-RPC without modification - even > with OKey fields. They're just POJOs and they serialize fine. > > * Builtin facilities to help with renaming fields and transforming > data during schema migration. > > * Configurable automatic retries for DatastoreTimeoutExceptions > (finally get rid of the 0.1% trickle of failures!). > > * Zero external dependencies - no Spring, no Guice, not even a logger > (it just wasn't necessary). Just one lonely 36K jar. > > * Objectify will work nicely with your DI framework. Static > singletons are not required. > > * Negligible impact on cold start time. > > * Thorough unit test suite. > > * Simple, easy-to-read, well-documented code. Not counting the > tests, there's actually only ten source files plus three annotations. > About 2,000 lines including whitespace and javadocs. > > There is ample documentation athttp://code.google.com/p/objectify-appengine/, > but some code examples > should make this clear: > > Basic operations: > > @Entity > class Car { > �...@id String vin; // Can be Long, long, or String > String color; > Date registered; > > } > > Objectify ofy = ObjectifyService.begin(); > ofy.put(new Car("123123", "red")); > Car c = ofy.get(Car.class, "123123"); > ofy.delete(c); > > OQuery<Car> query = ObjectifyService.newQuery(Car.class); > query.filter("registered <", lastYear).sort("color"); > List<Car> cars = ofy.prepare(query).asList(); > > Some more sophsticated examples: > > @Entity > class Employee { > �...@id long id; // primitive long is never autogenerated > �...@parent OKey<Company> employer; > > // field getting renamed > �...@oldname("boss") OKey<Employee> manager; > > String firstName; > String lastName; > > // we used to store fullName, now we store first and last separately > �...@oldname("fullName") public void oldWay(String fullName) > { > String[] split = fullName.split(" "); > firstName = split[0]; > lastName = split[1]; > } > > } > > Here's an example of interleaving a transactional session with a > nontransactional session: > > Objectify ofyNoTxn = ObjectifyService.begin(); > Objectify ofyTxn = ObjectifyService.beginTransaction(); > try > { > Foo f = ofyTxn.get(Foo.class, "k123"); > Bar b = ofyNoTxn.get(f.barKey); > > if (b.wantsUp()) > f.increment(); > else > f.decrement(); > > ofyTxn.put(f); > > ofyTxn.getTxn().commit();} > > finally > { > if (ofy.getTxn().isActive()) > ofy.getTxn().rollback(); > > } > > The full docs are here: > > http://code.google.com/p/objectify-appengine/ > > What doesn't it do? > > * It doesn't work with any datastore other than GAE. > > * It doesn't manage relationships for you - if you want cascading > deletes, collection proxies, and all the advantages and disadvantages > of that - you want JDO/JPA. I find managing this myself pretty easy, > and well worth the transparency. > > * No support yet for polymorphism. It won't require major structural > changes to add though. > > * It doesn't suck. Or so I am told. > > Jeff
-- You received this message because you are subscribed to the Google Groups "Google App Engine for Java" group. To post to this group, send email to google-appengine-j...@googlegroups.com. To unsubscribe from this group, send email to google-appengine-java+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/google-appengine-java?hl=en.