<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1936942592343397099</id><updated>2011-12-16T20:12:14.350-08:00</updated><category term='MongoDB'/><category term='JCP'/><category term='LINQ'/><category term='JPA'/><category term='java'/><category term='JPQL'/><category term='Typesafe'/><category term='JDOQL'/><category term='AppEngine'/><category term='GAE'/><category term='Persistence'/><category term='Criteria'/><category term='Oracle'/><category term='JDO'/><category term='hbase'/><category term='NoSQL'/><category term='DataNucleus'/><category term='TCK'/><category term='AccessPlatform'/><category term='primary-key'/><category term='Excel'/><title type='text'>DataNucleus</title><subtitle type='html'>The ultimate in flexible standardised Java persistence to any conceivable type of datastore</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Data Nucleus</name><uri>http://www.blogger.com/profile/06897027554521041521</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_oe9VRBj6u4E/SOe0z_TK4KI/AAAAAAAAAA0/5zjy0zmifUk/S220/DN.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-7940009330975722000</id><published>2011-11-05T07:15:00.000-07:00</published><updated>2011-11-05T10:50:45.282-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='GAE'/><category scheme='http://www.blogger.com/atom/ns#' term='AppEngine'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>GAE/J and DataNucleus v3 - Part 2</title><content type='html'>In the &lt;a href="http://datanucleus.blogspot.com/2011/08/gaej-and-datanucleus-v3.html"&gt;previous post&lt;/a&gt; we saw some initial changes to make GAE/J DataNucleus plugin work with the latest version of DataNucleus plugins. In this post we describe some further features of interest to GAE users that they weren't able to use before.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Storage Version&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;With v2 of the plugin it will, by default, persist using a new "storage version". In v1 of the plugin it persisted no explicit information about relations, and instead relied on doing queries for parent key to find related objects; obviously when all relations were owned then this was valid. In v2 of the plugin it persists a property in the Entity for each relation (containing the Key(s) of the related object(s)), at the owner side always. In the case of unowned relations (see below) it also will persist a property in the Entity at the non-owner side of a bidirectional relation. Obviously all existing data uses v1 of the storage version, but don't let that concern you since the plugin will check for presence of this property, and if not present then fall back to v1 behaviour to get the related objects. As entities are updated the data will be migrated to v2 storage version (a migration tool to do the job in one pass is in the works also).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: inherit;"&gt;&lt;u&gt;&lt;b&gt;Unowned Relations&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;By default in GAE/J all relations are &lt;b&gt;owned&lt;/b&gt; meaning that any child objects have the parent object Key as part of their Key, and persisted as part of the same &lt;i&gt;entity-group&lt;/i&gt;. This is obviously useful in optimising retrieval of data, but there are times when you simply want your model persisting and not have imposition of &lt;i&gt;ownership&lt;/i&gt;. In v2 of the plugin you can have &lt;b&gt;unowned&lt;/b&gt; relations, where each object is in its own &lt;i&gt;entity-group&lt;/i&gt;. To define a relation like this, see the following example&lt;br /&gt;&lt;pre&gt;@PersistenceCapable&lt;br /&gt;public class A&lt;br /&gt;{&lt;br /&gt;    @Persistent(primaryKey="true", valueStrategy=IdGeneratorStrategy.IDENTITY) &lt;br /&gt;    long id;&lt;br /&gt;&lt;br /&gt;    @Unowned&lt;br /&gt;    B b;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@PersistenceCapable&lt;br /&gt;public class B&lt;br /&gt;{&lt;br /&gt;    @Persistent(primaryKey="true", valueStrategy=IdGeneratorStrategy.IDENTITY) &lt;br /&gt;    long id;&lt;br /&gt;&lt;br /&gt;    @Unowned&lt;br /&gt;    @Persistent(mappedBy="b")&lt;br /&gt;    A a;&lt;br /&gt;&lt;br /&gt;    String name;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;So when we persist an object of type A with related B it will do the following&lt;br /&gt;&lt;ol&gt;&lt;li&gt;PUT the A, generating its Key, but without property for B&lt;/li&gt;&lt;li&gt;PUT the B, generating its Key, and with a property referring to the key of A&lt;/li&gt;&lt;li&gt;PUT the A with the property referring to the key of B.&lt;/li&gt;&lt;/ol&gt;It should be noted that the &lt;b&gt;@Unowned&lt;/b&gt; annotation is simply a shortcut for &lt;b&gt;@Extension&lt;/b&gt;(vendorName="datanucleus", key="gae.unowned", value="true") &lt;br /&gt;&lt;br /&gt;Be aware that if you persist unowned relations in a transaction then you will need to have multi-entity-group transactions enabled, since each object is in its own entity group.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: inherit;"&gt;&lt;u&gt;&lt;b&gt;Datastore Identity&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;With JDO the user has the choice of having their own primary key field (application-identity), or having the identity of the object defined for them (datastore-identity). GAE v1 only allowed application-identity. In v2 of the GAE DN plugin it also allows datastore-identity. To give an example&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;@PersistenceCapable&lt;br /&gt;@DatastoreIdentity(strategy=IdGeneratorStrategy.IDENTITY)&lt;br /&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div style="font-family: inherit;"&gt;So with this class it will persist an Entity and its Key will use IDENTITY strategy. &lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Interface Fields&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;With v2 of the plugin you can now have fields of interface type (representing a persistable type) and persist them as you would normally do. Refer to the &lt;a href="http://www.datanucleus.org/products/accessplatform/jdo/orm/interfaces.html"&gt;DataNucleus docs&lt;/a&gt; for how to do it (paying particular attention to the type of the field in metadata)&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;br /&gt;That's a brief summary of some of the more noteworthy improvements, and hopefully now GAE/J using JDO (or JPA) is a much more pleasant place to be, and you can refer almost directly to the DataNucleus docs for many more features now. In addition to the above changes, and in fixing various other minor bugs, the code structure has been changed quite a bit so future enhancements ought to be much more rapidly achievable&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-7940009330975722000?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/7940009330975722000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/11/gaej-and-datanucleus-v3-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/7940009330975722000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/7940009330975722000'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/11/gaej-and-datanucleus-v3-part-2.html' title='GAE/J and DataNucleus v3 - Part 2'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-8990814077373023472</id><published>2011-08-15T08:48:00.000-07:00</published><updated>2011-11-05T07:23:41.459-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='AppEngine'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>GAE/J and DataNucleus v3 - Part 1</title><content type='html'>&lt;div style="font-family: inherit;"&gt;Some time ago I wrote a post about GAE/J and how it provides JDO/JPA. It had many limitations and shortcomings. Recently we have had the chance to update their DataNucleus plugin to work with version 3.0. Here are the major changes that users of that plugin will see if they build and use GAE/J DataNucleus plugin from &lt;a href="http://code.google.com/p/datanucleus-appengine/"&gt;SVN trunk&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;u&gt;&lt;b&gt;JDOQL/JPQL : Support for methods/operators&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;If a user sets the query extension/hint &lt;i&gt;"datanucleus.query.evaluateInMemory"&lt;/i&gt; then the query will be evaluated in-memory. This has an obvious drawback in terms of memory utilisation (if the number of results is large), but the big plus is that it will evaluate almost all JDOQL/JPQL syntax.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;b&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;u&gt;&lt;b&gt;JDOQL : Support for input candidate collection&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;You can now specify the instances that you want to query over using &lt;i&gt;query.setCandidateCollection(...)&lt;/i&gt;. Means that you have a list of instances and can query which of them match a particular filter criteria.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;&lt;b&gt;Primary Key Types&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Previously you could only have &lt;i&gt;Long&lt;/i&gt;, &lt;i&gt;String&lt;/i&gt; or &lt;i&gt;Key&lt;/i&gt;. You can now also have &lt;i&gt;long&lt;/i&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;u&gt;&lt;b&gt;Plugin package naming&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Now uses &lt;i&gt;com.google.appengine.datanucleus&lt;/i&gt; as its package root, hence not using the DataNucleus-owned domain.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;JDOQL/JPQL setResultClass&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;This is now supported for the standard types of result classes, so you no longer need to convert manually the result into your required type.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Value Generation&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;GAE/J users can now make use of other DataNucleus value generators, such as "&lt;i&gt;uuid&lt;/i&gt;", "&lt;i&gt;uuid-hex&lt;/i&gt;" &lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;PersistenceManagerFactory&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;The PersistenceManagerFactory used is now the standard DataNucleus PMF, not any custom GAE variant. To be specific the PersistenceManagerFactoryClass is now &lt;i&gt;org.datanucleus.api.jdo.JDOPersistenceManagerFactory&lt;/i&gt;. If you want to have a singleton PMF, simply set the persistence property &lt;i&gt;datanucleus.singletonPMFForName&lt;/i&gt; to &lt;i&gt;true&lt;/i&gt;. This will then return any existing PMF if present for the requested persistence-unit, or create it if not present.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;EntityManagerFactory&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;The EntityManagerFactory used is now the standard DataNucleus EMF, not any custom GAE variant. To be specific the PersistenceProvider is &lt;i&gt;org.datanucleus.api.jpa.PersistenceProviderImpl&lt;/i&gt;. If you want to have a singleton EMF, simply set the persistence property &lt;i&gt;datanucleus.singletonEMFForName&lt;/i&gt; to &lt;i&gt;true&lt;/i&gt;. This will then return any existing EMF if present for the requested persistence-unit, or create it if not present.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;JPA2&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;By using DataNucleus v3 you now have available all of the changes made in JPA2, so things like Criteria queries, metamodel, etc.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;JDO3&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;By using DataNucleus v3 you now have available all of the changes made in JDO3.0/JDO3.1. This means query timeouts, metadata API, enhancer API, as well as the DataNucleus proposal for &lt;a href="http://datanucleus.blogspot.com/2010/11/jdo-typesafe-vs-jpa-criteria.html"&gt;Typesafe JDO queries&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Level2 Caching&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;Level2 Caching is enabled by default, using an internal map-based cache. You can improve this further by setting the persistence property &lt;i&gt;datanucleus.cache.level2.type&lt;/i&gt; to "javax.cache" and include datanucleus-cache.jar in your CLASSPATH. This will then cache using GAE Memcache&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Non-transactional Persistence&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;DataNucleus non-transactional behaviour is different now, with any call to pm.makePersistent, pm.deletePersistent, em.persist, em.merge, em.remove being atomic, sent to the datastore immediately. Any updates to fields via setters are still queued.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;JPA RetainValues&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;JPA usage, by default, has &lt;i&gt;datanucleus.RetainValues&lt;/i&gt; set to true now. This means that when you commit a transaction the object will retain the values of its fields (previously it migrated to hollow state).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Persistence of other java types&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;In GAE/J v1 you can only persist fields of the following types : primitive, primitive wrapper, String, Date, Enum, BigDecimal, some com.google.appengine types, as well as Collection types. With v2 you can now persist fields of types Currency, Locale, Timezone, BigInteger, Color, Point, StringBuffer, Jodatime, javax.time, and many more.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Be aware though ... there is more to come&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-8990814077373023472?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/8990814077373023472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/08/gaej-and-datanucleus-v3.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8990814077373023472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8990814077373023472'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/08/gaej-and-datanucleus-v3.html' title='GAE/J and DataNucleus v3 - Part 1'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5503433314538660169</id><published>2011-03-03T04:17:00.000-08:00</published><updated>2011-03-08T02:07:18.062-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Performance, benchmarking</title><content type='html'>Every so often some individual or group decides they're going to "invent" a new benchmark. They ignore all that have been done before (like PolePos) maybe due to &lt;i style="color: #ffd966;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Not_Invented_Here"&gt;NotInventedHereSyndrome&lt;/a&gt;&lt;/i&gt;, or maybe due to &lt;i style="color: #ffe599;"&gt;"&lt;span style="color: #f1c232;"&gt;oh someone who helped write that was related to some datastore therefore it must be dodgy"&lt;/span&gt;&lt;/i&gt;. While it is highly likely that existing benchmarks don't include their particular specific case, they never make any reference to what was there before that people are familiar with. They make minimal efforts at configuring other persistence solutions other than what is their favourite or what they have experience with, and then publish their results with a flourish to websites.&lt;br /&gt;&lt;br /&gt;Such benchmarks have been known to draw conclusions that you have a standard performance difference across all types of tests. Anyone who has ever looked at the persistence process would know that this conclusion is flawed since good persistence solutions all provide particular features, and by turning on these features you get beneficial things at the expense of some performance, and so certain operations will be better with one tool than with another. Hibernate has some good features, DataNucleus has some good features. If you enable particular features you get poorer performance in other areas. &lt;br /&gt;&lt;br /&gt;The other aspect of their conclusion is that they simply want a headline grabber black and white this is better than that. They seemingly aren't interested in thinking about the different methods employed by the software under test and the particular options. If I was exploring the topic of performance (and its an interesting topic, that can be useful in influencing priorities) I'd want to think about what I was asking the software to do and, bearing in mind that these benchmarks use open source software, and I'd have information available as to how a particular implementation attempts to do something. This could then be termed &lt;b&gt;constructive benchmarking&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Recently we had one which took a flat class, no inheritance or relationships, and persisted it, ... many times ... and then called itself a "Detailed Comparison". While this may be an operation that an application may need to do, the response time for the persist of an object of this form would not differ by any perceptible amount to the end user of that software. If a user is wanting to persist a large number of objects (like in bulk loading), then this would typically be performed in a background task anyway. DataNucleus has never been optimised for such a task (it would logically be better at complex object graphs due to the process it uses for detection of changes), but even with it, is actually configurable to give pretty good performance. As above, it's good at some things and less good at others. Anyone claiming to make a "detailed comparison" would have bothered to try it on a range of cases, to look at the full capabilities, to look at outstanding issues etc.&lt;br /&gt;&lt;br /&gt;Here, to give you something to talk about. I just ran a flat class&lt;br /&gt;&lt;pre&gt;@Entity&lt;br /&gt;public class A&lt;br /&gt;{&lt;br /&gt;    @Id&lt;br /&gt;    Long id;&lt;br /&gt;&lt;br /&gt;    String name;&lt;br /&gt;&lt;br /&gt;    public A(long id, String name)&lt;br /&gt;    {&lt;br /&gt;        this.id = id;&lt;br /&gt;        this.name = name;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;I ran it through the following persistence code&lt;br /&gt;&lt;pre&gt;EntityManager em = emf.createEntityManager();&lt;br /&gt;EntityTransaction txn = em.getTransaction();&lt;br /&gt;txn.begin();&lt;br /&gt;for (int i=0;i&amp;lt;10000;i++)&lt;br /&gt;{&lt;br /&gt;    A a = new A(i, "First");&lt;br /&gt;    em.persist(a);&lt;br /&gt;}&lt;br /&gt;txn.commit();&lt;/pre&gt;&lt;br /&gt;I used the config of the aforementioned (Hibernate) users for running Hibernate, and tuned DataNucleus myself. And the runtimes ?  &lt;b&gt;Hibernate&lt;/b&gt; (3.6.1.Final) took &lt;b&gt;8164ms&lt;/b&gt;, and &lt;b&gt;DataNucleus&lt;/b&gt; (SVN trunk on 3/Mar/2011) took &lt;b&gt;7227ms&lt;/b&gt; (using HSQLDB 1.8.0.4 embedded). So on that case &lt;b&gt;DataNucleus was faster&lt;/b&gt;. Is this significant ? Well no, since as I already explained it's a particular case, but demonstrates the principle clearly enough. We can all turn on/off particular options and get some results. Besides which persisting 10000 objects in just 7-8 seconds (on this PC!) is pretty impressive in anyone's book and never a bottleneck in a normal application.&lt;br /&gt;&lt;br /&gt;If you are performing something of the nature of a flat object bulk persist you would not use transactions to avoid the overhead, and you would turn off various features that are not of interest - managed relationships, persistence-by-reachability-at-commit, L2 caching even. Then if using an identity generator you would allocate large blocks of values with your metadata. That said, if you are so serious about performance and persisting flat objects to RDBMS then anyone sensible would use either JDBC direct, or a JDBC wrapper like MyBatis or SpringJDBC. This is &lt;b&gt;"right tool for the job"&lt;/b&gt;. Since the benchmark was provided by a group of Hibernate users (they provide various Hibernate tutorials and nothing for any other persistence implementation) we only have to assume that this must be what they think is the "best tool" - if so why not reproduce your benchmark with well-written JDBC and let us know what you find. I even posed this question about applicability of a flat class on their blog and my comment was deleted. Whether it was deleted by them, or by the blogger system I've no idea, but it was there for an hour and at that point was deleted. Our blog has never lost comments, and it's on the same host system.&lt;br /&gt;&lt;br /&gt;One of the (undeleted) comments on their benchmark was from the author of an ODBMS who seems to like to decide publically what I ought to spend my spare time on. Is he a commercial client ? no. Is his software open source ? no. Or free ? not if I want to use it on anything serious. The response to him is simple : &lt;i style="color: #ffd966;"&gt;let me decide what I spend my time on, and you concentrate on your own software; I don't tell you what to do. It's an ancient custom called "respect"&lt;/i&gt; - sadly symptomatic of the attitudes in the IT profession.&lt;br /&gt;&lt;br /&gt;A benchmark to use as the basis for choosing what software you use in your own application needs to cover the different persistence operations that you will perform. If you have a web application that creates a few objects, deletes a few, updates a few, etc continually, then the likelihood is that the performance will not impact on you or your end users to one iota. What will impact on you is whether the persistence solution allows you to do what you want to do or whether it has a large number of unfixed bugs that force you to continually implement workarounds or compromises on your design. Why not have a look through the issue tracker of the software and see what types of problems people are having, and how long the issues have existed?&lt;br /&gt;&lt;br /&gt;DataNucleus 3.0 development is initially focussing on architecture, since we believe in getting the architecture right first to take the software to the level we think it needs to be. This means that in early milestones (the benchmark referenced above decided to use 3.0M1) we spend time on refactoring etc, and not on performance. This doesn't mean that performance isn't important, just that we feel our users want to be able to perform their tasks first and foremost and then speed things up later. This is the same methodology employed by PostgreSQL to much success, who for years had to listen to &lt;i&gt;"MySQL is faster"&lt;/i&gt; comments. Even with that general philosophy anyone using current SVN code would already see some very noticeable speed up in non-transactional persistence performance, and anyone using the MongoDB plugin would also see much more optimised insert performance. These benefits are due to extending the architecture to do some things that we've wanted to do for some time but didn't since we wanted to maintain backwards compatibility and due to resourcing.&lt;br /&gt;&lt;br /&gt;Next time you look at some "performance benchmark" we suggest that you bear this in mind. We won't be spending our time analysing their results, or responding to their claims. This is because we'd rather spend it developing this software, rather than "mine is better than yours" negative mentality discussions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5503433314538660169?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5503433314538660169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/03/performance-benchmarking.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5503433314538660169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5503433314538660169'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/03/performance-benchmarking.html' title='Performance, benchmarking'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-3055488287699746895</id><published>2011-02-13T02:19:00.000-08:00</published><updated>2011-02-16T10:35:15.152-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><category scheme='http://www.blogger.com/atom/ns#' term='NoSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>DataNucleus v3 and MongoDB</title><content type='html'>There has obviously been a recent shift to look at highly scalable datastores for use in "the cloud". Google wrote a plugin for their own BigTable datastore back in 2009, providing access to some of the features of JDO/JPA. Unfortunately they &lt;a href="http://datanucleus.blogspot.com/2010/01/gaej-and-jdojpa.html"&gt;didn't have the intention of providing a full and fair reflection of those persistence specifications&lt;/a&gt;, and so reaction to it was mixed. Some people attempted to argue that APIs like JDO did not match these types of datastores (I see nothing in the API or query language of JDO that led to this conclusion, but anyway) and that using standard APIs on them was inappropriate; they were asked to provide concrete examples of features of these datastores could not be handled adequately by JDO but unfortunately didn't come up with anything.&lt;br /&gt;&lt;br /&gt;With DataNucleus v3 we have the opportunity to spend some time on providing good support for these types of datastores, adding support for missing features. A &lt;a href="http://datanucleus.blogspot.com/2011/01/datanucleus-v3-and-hbase.html"&gt;previous blog post&lt;/a&gt; documented efforts to upgrade the support for HBase. In this blog post we describe the features in the new plugin for the &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt; document-based "NoSQL" store.&lt;br /&gt;&lt;br /&gt;Features that this plugin currently supports include&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Support for single MongoDB instances, and for MongoDB replica sets&lt;/li&gt;&lt;li&gt;Support for application identity (defined by the user), and datastore identity (surrogate field in the JSON document)&lt;/li&gt;&lt;li&gt;Basic persistence/update/delete of objects&lt;/li&gt;&lt;li&gt;Support for persistence of (unembedded) Collections/Maps/arrays by way of storing the identity of any related object(s) in the field.&lt;/li&gt;&lt;li&gt;Persistence of related objects (1-1/N-1) as "flat" embedded, where all fields of the related object are fields of the owner JSON document. This also supports nested related objects (unlimited depth).&lt;/li&gt;&lt;li&gt;Persistence of related objects (1-1/N-1) as nested embedded, where the related object is stored as a nested JSON document within the owner JSON document. This also supports nested related objects (unlimited depth).&lt;/li&gt;&lt;li&gt;Persistence of related collections/arrays (1-N) as nested embedded, where the related objects are stored as an array of nested JSON documents. This also supports nested relations.&lt;/li&gt;&lt;li&gt;Persistence of related maps (1-N) as nested embedded, where the related map is a nested array of map entries with fields "key","value". Supports nested relations.&lt;/li&gt;&lt;li&gt;Persistence of fields as serialised.&lt;/li&gt;&lt;li&gt;Polymorphic queries. If the query requests a class or subclasses then that is what is returned. This implies the execution of any query against the MongoDB collection for each of the possible candidate classes.&lt;/li&gt;&lt;li&gt;Access to the native MongoDB "DB" object via the standard JDO datastore connection accessor&lt;/li&gt;&lt;li&gt;Support for persistence of object version, stored in a separate field in the JSON document and support for optimistic version checking&lt;/li&gt;&lt;li&gt;Support for "identity" value generation using the MongoDB "_id" field value. The only restriction on this is that a field/property using "identity" value generation has to be of type String&lt;/li&gt;&lt;li&gt;Support for "increment" value generation (numeric fields).&lt;/li&gt;&lt;li&gt;Support for SchemaTool creation/deletion of schemas. This supports the document collection for the classes, as well as any indices required (including unique).&lt;/li&gt;&lt;li&gt;JDOQL/JPQL querying, including support for fetch groups, so you can restrict how much data is returned by the query.&lt;/li&gt;&lt;li&gt;Basic JDOQL/JPQL filter clauses (comparison operations) are evaluated in the datastore where possible.&lt;/li&gt;&lt;li&gt;Support for running queries on MongoDB slave instances.&lt;/li&gt;&lt;li&gt;Support for persistence of discriminators, so a user can store multiple classes into the same MongoDB collection, and we use the discriminator to determine the object type being returned.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;As you can see, we already provide a very good JDO (and JPA) capability for MongoDB, and the feature list is &lt;a href="http://www.datanucleus.org/products/accessplatform_3_0/datastore_features.html"&gt;shown as a matrix here&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Input to this plugin is obviously desired, particularly from people with more intimate knowledge of MongoDB. Source code can be found at &lt;a href="http://datanucleus.svn.sourceforge.net/viewvc/datanucleus/platform/store.mongodb/trunk/"&gt;SourceForge&lt;/a&gt;, and issues are tracked via the &lt;a href="http://www.datanucleus.org/servlet/jira/browse/NUCMONGODB"&gt;NUCMONGODB project in JIRA&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-3055488287699746895?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/3055488287699746895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/02/datanucleus-v3-and-mongodb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/3055488287699746895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/3055488287699746895'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/02/datanucleus-v3-and-mongodb.html' title='DataNucleus v3 and MongoDB'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-668108905127797523</id><published>2011-01-24T06:57:00.001-08:00</published><updated>2011-01-29T06:01:33.826-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JCP'/><category scheme='http://www.blogger.com/atom/ns#' term='Oracle'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>JPA : TCK request and JPA2.1</title><content type='html'>It is now almost exactly a year since we submitted a request for access to the JPA2 TCK (JSR0317). We provided everything requested of us by Oracle, and we still haven't received the JPA2 TCK. Just to say Happy Anniversary Oracle on this evidently controversial request. The only possible reasons that I can think of for lack of provision of this are either &lt;span style="font-style:italic;"&gt;incompetence&lt;/span&gt;, or &lt;span style="font-style:italic;"&gt;deliberate prevention of access&lt;/span&gt;. Needless to say, we no longer wish to have access to this TCK.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;On a related note I was asked whether I'd be participating in the JPA2.1 (JSR0338) expert group. I did think about it, no really! :-) But then I remembered that I spent many hours sending emails chasing Oracle employees to fulfil the request for the JPA2.0 TCK all to no avail. We also have to remember that JPA was born out of politics nothing more. Consequently the answer had to be a NO.&lt;br /&gt;&lt;br /&gt;I have every willingness to participate in truly open standards on Java persistence, based on technical reasons. Any such participation would be with open mailing-lists/forums, and an open testing capability so that anyone can validate the compliance of any implementation. JPA, and the JCP process it operates under, is not that; JPA standardises things like "Criteria" that is widely recognised as inelegant (many call it &lt;span style="font-style:italic;"&gt;ugly&lt;/span&gt; actually) and hard to use. A standard should take something that has become accepted as a good way of doing something (such as QueryDSL, for example) and convert it into something coherent with a clean API (like what we did with &lt;a href="http://datanucleus.blogspot.com/2010/11/jdo-typesafe-vs-jpa-criteria.html"&gt;JDO Typesafe&lt;/a&gt;); it should not invent something and impose it on people. The JPA philosophy is simply wrong in this respect. I wish them good luck with JPA2.1, and DataNucleus will, at some point (typically as soon as the spec is made public), implement what they come up with, but I will not be party to its "design".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-668108905127797523?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/668108905127797523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/01/jpa-tck-request-and-jpa21.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/668108905127797523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/668108905127797523'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/01/jpa-tck-request-and-jpa21.html' title='JPA : TCK request and JPA2.1'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-4345494953920558838</id><published>2011-01-13T10:40:00.000-08:00</published><updated>2011-01-20T08:17:02.631-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='NoSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='hbase'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>DataNucleus v3 and HBase</title><content type='html'>DataNucleus AccessPlatform v3 provides an opportunity to bring some of our other datastore plugins closer to the standard of the more mature long-supported datastores (e.g RDBMS). In the case of HBase, the plugin provided with v2.0 offered basic persistence and querying, at best. In v3 this is already much improved.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;You can now run &lt;a href="http://www.datanucleus.org/products/accessplatform_3_0/schematool.html"&gt;SchemaTool&lt;/a&gt; against HBase. This operates in either "create" or "delete" modes, and allows you to manage the schema required by your persistable classes.&lt;/li&gt;&lt;li&gt;When a relationship was persisted with v2.0 it simply serialised the related object. This broke JDO/JPA cascade rules. In v3 the column for the relation in the owner stores the identity (or identities when persisting multi-value relations). This also provides correct cascading of persist and update.&lt;/li&gt;&lt;li&gt;When a String field was persisted in v2.0 it was Java serialised, meaning that it was not readable with something like "hbase shell". In v3.0 String/char fields are persisted as the bytes of the field value, hence readable.&lt;/li&gt;&lt;li&gt;With v2.0 we provided value generation using "uuid", "uuid-hex", etc simple generators, but not accessible by default. In v3.0 the default (JDO "native", JPA "auto") is "uuid-hex", and we also provide an "increment" generator (contrib from Peter Rainer).&lt;/li&gt;&lt;li&gt;In v2.0 we only supported "application identity". In v3.0 we also support "datastore identity" (surrogate identity column).&lt;/li&gt;&lt;li&gt;In v2.0 we didn't support storing a version against the object. In v3.0 we do allow this.&lt;/li&gt;&lt;li&gt;You can now embed persistable fields into the table of the owning object, and also nested embedded fields.&lt;/li&gt;&lt;li&gt;Now supports HBase 0.90&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Obviously there is still much more that can be done - see the &lt;a href="http://www.datanucleus.org/products/accessplatform_3_0/datastore_features.html"&gt;datastore features comparison table&lt;/a&gt;. One that will give more performance is to handle more of any query filter in the datastore, rather than just processing all in-memory. Contributions for this and other things are very welcome. But then we aren't even at 3.0 Milestone 1 yet ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-4345494953920558838?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/4345494953920558838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2011/01/datanucleus-v3-and-hbase.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4345494953920558838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4345494953920558838'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2011/01/datanucleus-v3-and-hbase.html' title='DataNucleus v3 and HBase'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-8879323318437311929</id><published>2010-11-08T23:24:00.000-08:00</published><updated>2011-03-05T00:35:50.624-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Criteria'/><category scheme='http://www.blogger.com/atom/ns#' term='Typesafe'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>JDO Typesafe .vs. JPA Criteria</title><content type='html'>JPA2 introduced its "Criteria" queries, providing an API for typesafe query generation without the need to hardcode field names etc in queries; it built on the approach of Hibernate Criteria. DataNucleus includes a proposal for JDO "Typesafe" queries. It takes a slightly different approach aiming at usability and elegance. In this blog post we compare some queries using the two APIs.&lt;br /&gt;&lt;br /&gt;In these examples we have two classes, &lt;span style="font-weight: bold;"&gt;Inventory&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;Product&lt;/span&gt;, where Inventory has a set of products.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;Select of persistable objects with simple filter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT p FROM Product p WHERE p.name = 'MP3 Extra'&lt;/pre&gt;&lt;br /&gt;whilst JDOQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT FROM Product WHERE this.name == 'MP3 Extra'&lt;/pre&gt;&lt;br /&gt;JPA Criteria would be&lt;br /&gt;&lt;pre&gt;CriteriaQuery&amp;lt;Product&amp;gt; criteria = builder.createQuery(Product.class);&lt;br /&gt;Root&amp;lt;Product&amp;gt; productRoot = criteria.from(Product.class);&lt;br /&gt;criteria.select(productRoot);&lt;br /&gt;criteria.where(builder.equal(productRoot.get(Product_.name), "MP3 Extra"));&lt;br /&gt;List&amp;lt;Product&amp;gt; products = em.createQuery(criteria).getResultList();&lt;/pre&gt;&lt;br /&gt;JDO Typesafe is&lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.filter(cand.name.eq("MP3 Extra")).executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Select of result of attributes of persistable objects&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT p.value, p.manufacturer FROM Product p WHERE p.name = 'MP3 Extra'&lt;/pre&gt;&lt;br /&gt;JDOQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT this.value, this.manufacturer FROM Product WHERE this.name == 'MP3 Extra'&lt;/pre&gt;&lt;br /&gt;JPA Criteria would be&lt;br /&gt;&lt;pre&gt;CriteriaQuery criteria = builder.createQuery();&lt;br /&gt;Root&amp;lt;Product&amp;gt; productRoot = criteria.from(Product.class);&lt;br /&gt;criteria.multiselect(productRoot.get(Product_.value), &lt;br /&gt;productRoot.get(Product_.manufacturer);&lt;br /&gt;criteria.where(builder.equal(productRoot.get(Product_.name), "MP3 Extra"));&lt;br /&gt;List&amp;lt;Object[]&amp;gt; results = em.createQuery(criteria).getResultList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;JDO Typesafe is&lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;List&amp;lt;Object[]&amp;gt; results =&lt;br /&gt;tq.filter(cand.name.eq("MP3 Extra"))&lt;br /&gt;.executeResultList(cand.value, cand.manufacturer);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Select of aggregate of attribute of persistable objects&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT MAX(p.value) FROM Product p WHERE p.name = "MP3 Extra"&lt;/pre&gt;&lt;br /&gt;JDOQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT MAX(this.value) FROM Product WHERE this.name == "MP3 Extra"&lt;/pre&gt;&lt;br /&gt;JPA Criteria would be&lt;br /&gt;&lt;pre&gt;CriteriaQuery&amp;lt;Integer&amp;gt; criteria = builder.createQuery(Integer.class);&lt;br /&gt;Root&amp;lt;Product&amp;gt; productRoot = criteria.from(Product.class);&lt;br /&gt;criteria.select(builder.max(productRoot.get(Product_.value)));&lt;br /&gt;criteria.where(builder.equal(productRoot.get(Product_.name), "MP3 Extra"));&lt;br /&gt;Object result = em.createQuery(criteria).getSingleResult();&lt;/pre&gt;&lt;br /&gt;JDO Typesafe is&lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;Integer result =&lt;br /&gt;tq.filter(cand.name.eq("MP3 Extra")).executeResultUnique(Integer.class, cand.value.max());&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;Select of persistable objects with simple filter and parameter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT p FROM Product p WHERE p.name = :param&lt;/pre&gt;&lt;br /&gt;whilst JDOQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT FROM Product WHERE this.name == :param&lt;/pre&gt;&lt;br /&gt;JPA Criteria would be&lt;br /&gt;&lt;pre&gt;CriteriaQuery&amp;lt;Product&amp;gt; criteria = builder.createQuery(Product.class);&lt;br /&gt;Root&amp;lt;Product&amp;gt; productRoot = criteria.from(Product.class);&lt;br /&gt;criteria.select(productRoot);&lt;br /&gt;ParameterExpression&amp;lt;String&amp;gt; valueParam = builder.parameter(String.class);&lt;br /&gt;criteria.where(builder.equal(productRoot.get(Product_.name), valueParam));&lt;br /&gt;TypedQuery&amp;lt;Product&amp;gt; query = em.createQuery(criteria);&lt;br /&gt;query.setParameter(valueParam, "MP3 Extra");&lt;br /&gt;List&amp;lt;Product&amp;gt; products = query.getResultList();&lt;/pre&gt;&lt;br /&gt;JDO Typesafe is&lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;List&amp;lt;Product&amp;gt; results =&lt;br /&gt;tq.filter(cand.name.eq(tq.stringParameter("prefix")))&lt;br /&gt;.setParameter("prefix", "MP3 Extra").executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;Select of persistable objects with joined filter condition&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT i FROM Inventory i JOIN i.products p WHERE (p.name = 'MP3 Extra')&lt;/pre&gt;&lt;br /&gt;JDOQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT FROM Inventory WHERE this.products.contains(var) &amp;amp;&amp;amp; var.name == "MP3 Extra"&lt;/pre&gt;&lt;br /&gt;JPA Criteria would be&lt;br /&gt;&lt;pre&gt;CriteriaQuery&amp;lt;Inventory&amp;gt; criteria = builder.createQuery(Inventory.class);&lt;br /&gt;Root&amp;lt;Inventory&amp;gt; invRoot = criteria.from(Inventory.class);&lt;br /&gt;criteria.select(invRoot);&lt;br /&gt;Join&amp;lt;Inventory, Product&amp;gt; productJoin = invRoot.join(Inventory_.products);&lt;br /&gt;criteria.where(builder.equal(productJoin.get(Product_.name), "MP3 Extra"));&lt;br /&gt;List&amp;lt;Inventory&amp;gt; inventories = em.createQuery(criteria).getResultList();&lt;/pre&gt;&lt;br /&gt;JDO Typesafe is&lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Inventory&amp;gt; tq = pm.newTypesafeQuery(Inventory.class);&lt;br /&gt;QProduct var = QProduct.variable("var");&lt;br /&gt;QInventory cand = QInventory.candidate();&lt;br /&gt;List&amp;lt;Inventory&amp;gt; results =&lt;br /&gt;tq.filter(cand.products.contains(var).and(var.name.eq("MP3 Extra"))).executeList();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;Select of persistable objects with subquery filter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JPQL single-string would be&lt;br /&gt;&lt;pre&gt;SELECT p FROM Product p WHERE p.value &amp;lt; (SELECT AVG(q.value) FROM Product q)&lt;/pre&gt;JDOQL single-string would be &lt;br /&gt;&lt;pre&gt;SELECT FROM Product WHERE this.value &amp;lt; (SELECT AVG(q.value) FROM Product q)&lt;/pre&gt;JPA Criteria would be &lt;br /&gt;&lt;pre&gt;CriteriaQuery&amp;lt;Product&amp;gt; criteria = builder.createQuery(Product.class);&lt;br /&gt;Root&lt;product&gt; productRoot = criteria.from(Product.class);&lt;br /&gt;criteria.select(productRoot);&lt;br /&gt;Subquery&amp;lt;Double&amp;gt; sub = criteria.subquery(Double.class);&lt;br /&gt;Root&amp;lt;Product&amp;gt; subRoot = sub.from(Product.class);&lt;br /&gt;criteria.where(builder.lt(productRoot.get(Product_.value), &lt;br /&gt;sub.select(builder.avg(subRoot.get(Product_.value)))));&lt;br /&gt;List&amp;lt;Product&amp;gt; products = em.createQuery(criteria).getResultList();&lt;/product&gt;&lt;/pre&gt;JDO Typesafe is &lt;br /&gt;&lt;pre&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;TypesafeSubquery&amp;lt;Product&amp;gt; tqsub = tq.subquery(Product.class, "q");&lt;br /&gt;QProduct candsub = QProduct.candidate("q");&lt;br /&gt;List&amp;lt;Product&amp;gt; results = &lt;br /&gt;tq.filter(cand.value.lt(tqsub.selectUnique(candsub.value.avg()))).executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you have seen, for all typesafe queries JDO Typesafe is more elegant and shorter. It requires no "builder" too. Access of a field of a class is one particular example, typing "cand.value" instead of "productRoot.get(Product_.value)"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-8879323318437311929?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/8879323318437311929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/11/jdo-typesafe-vs-jpa-criteria.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8879323318437311929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8879323318437311929'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/11/jdo-typesafe-vs-jpa-criteria.html' title='JDO Typesafe .vs. JPA Criteria'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-8390093073749043433</id><published>2010-11-02T03:07:00.000-07:00</published><updated>2010-11-09T01:31:27.487-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Typesafe'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>JDO Typesafe Queries : Part 3 - Examples</title><content type='html'>In two previous blog posts, we introduced the idea of having a &lt;a href="http://datanucleus.blogspot.com/2010/06/jdo-typesafe-refactorable-queries.html"&gt;typesafe refactor friendly API for queries for JDO&lt;/a&gt;, and then described &lt;a href="http://datanucleus.blogspot.com/2010/07/jdo-typesafe-refactorable-queries.html"&gt;typical expression types&lt;/a&gt; necessary to achieve that. In this blog post we take that a step further, particularly now that DataNucleus SVN has a proof of concept query API to fulfil this requirement.&lt;br /&gt;&lt;br /&gt;In these examples we have a class Product. Consequently we have a "query" class autogenerated - QProduct. Here is the QProduct class&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class QProduct &lt;br /&gt;    extends PersistableExpressionImpl&amp;lt;Product&amp;gt; &lt;br /&gt;    implements PersistableExpression&amp;lt;Product&amp;gt;&lt;br /&gt;{&lt;br /&gt;    public static QProduct candidate() {...} // candidate "this"&lt;br /&gt;    public static QProduct candidate(String name) {...}&lt;br /&gt;    public static QProduct parameter(String name) {...}&lt;br /&gt;    public static QProduct variable(String name) {...}&lt;br /&gt;&lt;br /&gt;    public NumericExpression&amp;lt;Long&amp;gt; id;&lt;br /&gt;    public StringExpression name;&lt;br /&gt;    public NumericExpression&amp;lt;Double&amp;gt; value;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;So, as you can see we have access to the persistable fields/properties of Product by way of public fields in its query class. Now on to some examples&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter only&lt;/span&gt;&lt;br /&gt;Here we select all Products that have a value less than 40.0&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;tq.filter(cand.value.lt(40.0));&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter + Order&lt;/span&gt;&lt;br /&gt;Here we select all Products that have a value less than 40.0 and ordering by their name&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;tq.filter(cand.value.lt(40.0)).orderBy(cand.name.asc());&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter + Order + Result&lt;/span&gt;&lt;br /&gt;Here we select the product name and product value for all Products that have a value less than 40.0 , ordering by their name&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;tq.filter(cand.value.lt(40.0)).orderBy(cand.name.asc());&lt;br /&gt;List&amp;lt;Object[]&amp;gt; results = tq.executeResultList(true, cand.name, cand.value);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter with Methods&lt;/span&gt;&lt;br /&gt;Here we select all Products that have a value less than 40.0 and name starting with "Wal", and ordering by their name&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;tq.filter(cand.value.lt(40.0).and(cand.name.startsWith("Wal")));&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter, using Parameters&lt;/span&gt;&lt;br /&gt;Here we select all Products that have a value less than 40.0, using a parameter&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate()&lt;br /&gt;tq.filter(cand.value.lt(tq.doubleParameter("param1"))).setParameter("param1", 40.0);&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Order + Range&lt;/span&gt;&lt;br /&gt;Here we select Products, ordering by the name and restrict to the first two&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;tq.orderBy(cand.name.asc()).range(0,2);&lt;br /&gt;List&amp;lt;Product&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter with Variable&lt;/span&gt;&lt;br /&gt;Here we select Inventory (which has a collection of Products) that contain a Product with a particular name&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Inventory&amp;gt; tq = pm.newTypesafeQuery(Inventory.class);&lt;br /&gt;QInventory cand = QInventory.candidate();&lt;br /&gt;QProduct var = QProduct.variable("var");&lt;br /&gt;tq.filter(cand.products.contains(var).and(var.name.startsWith("Wal")));&lt;br /&gt;List&amp;lt;Inventory&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filter with Subquery&lt;/span&gt;&lt;br /&gt;Here we select Products with a value less than the average value of any Product&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TypesafeQuery&amp;lt;Product&amp;gt; tq = pm.newTypesafeQuery(Product.class);&lt;br /&gt;QProduct cand = QProduct.candidate();&lt;br /&gt;TypesafeSubquery tqsub = tq.subquery(Product.class, "p");&lt;br /&gt;QProduct candsub = QProduct.candidate("p");&lt;br /&gt;tq.filter(cand.value.lt(tqsub.select(candsub.value.avg())));&lt;br /&gt;List&amp;lt;Inventory&amp;gt; results = tq.executeList();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see from the above queries we have no hard-coded class or field names, providing better refactorability. We can obviously make use of all JDOQL supported methods in the above queries, and define parameters and variables just like in the current JDOQL API.&lt;br /&gt;&lt;br /&gt;It should be noted that this JDOQL facility is much more elegant and requires less code than the equivalent queries using JPA "Criteria".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-8390093073749043433?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/8390093073749043433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/11/jdo-typesafe-queries-part-3-examples.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8390093073749043433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8390093073749043433'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/11/jdo-typesafe-queries-part-3-examples.html' title='JDO Typesafe Queries : Part 3 - Examples'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5098089202531965074</id><published>2010-07-14T11:05:00.000-07:00</published><updated>2010-07-15T03:21:48.299-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><title type='text'>Writing data to Excel from Java - the simple way</title><content type='html'>On the web you can find some blogs about how to use Apache POI to create an Excel spreadsheet. They typically contain reams of code just to add a simple table and some rows of data. It's always amazing the amount of suffering people put themselves through to perform simple tasks. An example is &lt;a href="http://www.techbrainwave.com/?p=554"&gt;this blog&lt;/a&gt; (there are &lt;a href="http://sanjaal.com/java/105/java-file/writing-to-excel-file-using-apache-poi/"&gt;others&lt;/a&gt;) which demonstrates some typical calls you will make using Apache POI to create a simple spreadsheet. Whilst that may represent what Apache POI requires, a user choosing to follow this way is inflicting unnecessary suffering on themselves, really. Read on ...&lt;br /&gt;&lt;br /&gt;Here's how we would achieve the same thing as the referenced blog using JDO and DataNucleus. Firstly lets create a class that equates to a row of data in the table.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@PersistenceCapable(table="SampleDataSheet1")&lt;br /&gt;public class SampleData&lt;br /&gt;{&lt;br /&gt;    @PrimaryKey @Column(name="Employer Name")&lt;br /&gt;    String employerName;&lt;br /&gt;    @Column(name="Designation")&lt;br /&gt;    String designation;&lt;br /&gt;    @Column(name="Country")&lt;br /&gt;    String country;&lt;br /&gt;&lt;br /&gt;    public SampleData(String e, String d, String c)&lt;br /&gt;    {&lt;br /&gt;       this.employerName = e;&lt;br /&gt;       this.designation = d;&lt;br /&gt;       this.country = c;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Now we define our datastore persistence properties (&lt;span style="font-style:italic;"&gt;datanucleus.properties&lt;/span&gt;)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;javax.jdo.PersistenceManagerFactoryClass=&lt;br /&gt;    org.datanucleus.jdo.JDOPersistenceManagerFactory&lt;br /&gt;javax.jdo.option.ConnectionURL=excel:file:test.xls&lt;/pre&gt;&lt;br /&gt;Finally let's do some persistence&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;PersistenceManagerFactory pmf = &lt;br /&gt;    JDOHelper.getPersistenceManagerFactory(“datanucleus.properties”);&lt;br /&gt;PersistenceManager pm = pmf.getPersistenceManager();&lt;br /&gt;Transaction tx = pm.currentTransaction();&lt;br /&gt;tx.begin();&lt;br /&gt;SampleData ds =&lt;br /&gt;    new SampleData(“Intelligent User”, “Software Engineer”, “Bolivia”);&lt;br /&gt;pm.makePersistent(ds);&lt;br /&gt;tx.commit();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and this generates the same output that was shown in the blog, just that the code is now readable, shorter, and uses standardised APIs, never mind the fact that you could conceivably just persist the same data to RDBMS, XML, ODF, ODBMS, Cassandra and many more datastores with a simple change of that datastore URL. Additionally it allows you to focus on objects, which is likely why you chose Java in the first place. Why put yourself through more pain ?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;[Needless to say, DataNucleus would also allow you to do the same using JPA]&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5098089202531965074?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5098089202531965074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/07/writing-data-to-excel-from-java-simple.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5098089202531965074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5098089202531965074'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/07/writing-data-to-excel-from-java-simple.html' title='Writing data to Excel from Java - the simple way'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-1020206604887469385</id><published>2010-07-13T11:51:00.001-07:00</published><updated>2010-07-13T11:51:32.471-07:00</updated><title type='text'>TJDO has left the building</title><content type='html'>As anyone who has been using DataNucleus (and JPOX before it) for some time will know, it all started out (in 2003) as TJDO. This project was forked to provide all of the missing functionality that JDO requires and users of that technology demand (starting with application identity, and all common ORM relationship patterns). Over the last 7 years components have been rewritten one-by-one&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Table handling code was upgraded to cater for JDO2 inheritance strategies&lt;/li&gt;&lt;br /&gt;&lt;li&gt;MetaData was rewritten to match the JDO2 definition (replacing TJDO's JDO1-style handling)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Transaction handling was rewritten to cater for XA transactions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mapping code was rewritten to split into java type handling and datastore handling&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;DataNucleus SVN trunk (v2.2) now removes the last significant component of TJDO ... its JDOQL implementation for RDBMS (known in v2.1 as "Legacy"); it is now totally replaced by the generic-query-expression-tree approach that allows many many additional JDOQL queries to execute. There still remain some TJDO vestiges but nothing of any significance. R.I.P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-1020206604887469385?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/1020206604887469385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/07/tjdo-has-left-building.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/1020206604887469385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/1020206604887469385'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/07/tjdo-has-left-building.html' title='TJDO has left the building'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5716630360151639549</id><published>2010-07-07T10:43:00.000-07:00</published><updated>2010-07-12T02:08:50.959-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><title type='text'>JDO Typesafe Queries : Part 2 - Expressions</title><content type='html'>Continuing on from the previous post, in order to be able to express components of a query in a Java style we need to represent all fields/properties/parameters/variables as &lt;span style="font-style:italic;"&gt;expressions&lt;/span&gt;. The type of the field/property/parameter/variable determines its expression type. Let's take an example&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Person&lt;br /&gt;{&lt;br /&gt;    String firstName;&lt;br /&gt;    String lastName;&lt;br /&gt;    int age;&lt;br /&gt;    Person bestFriend;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;We need to represent these field types with expressions, so let's start with&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;StringExpression - for Strings&lt;/li&gt;&lt;br /&gt;&lt;li&gt;NumericExpression - for int, long, short, double, float, Integer, Long, Short, Double, Float, BigDecimal, BigInteger etc&lt;/li&gt;&lt;br /&gt;&lt;li&gt;BooleanExpression - for boolean, Boolean&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ByteExpression - for byte, Byte&lt;/li&gt;&lt;br /&gt;&lt;li&gt;CharacterExpression - for char, Character&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DateExpression - for Date-based types&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ObjectExpression - for other Object-based types where we have no specific handling&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Ok, so this is all well and good and we can express &lt;span style="font-style:italic;"&gt;firstName&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt; as a StringExpression, and similarly &lt;span style="font-style:italic;"&gt;age&lt;/span&gt; is a NumericExpression. So for that we can do&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;QPerson person = QPerson.person;&lt;br /&gt;Query&amp;lt;Person&amp;gt; q = pm.newTypesafeQuery(person);&lt;br /&gt;Person bob = &lt;br /&gt;    q.filter(person.firstName.eq("Bob")).executeUnique();&lt;/pre&gt;&lt;br /&gt;To represent a persistable field (i.e a 1-1 relation, &lt;span style="font-style:italic;"&gt;bestFriend&lt;/span&gt; in the above example) we have another expression type &lt;span style="font-style:italic;"&gt;PersistableExpression&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;"Q" classes&lt;/h3&gt;&lt;br /&gt;Above you see use of metamodel query classes. We refer to them as "Q" classes currently, but the naming is arbitrary for now. So what does a "Q" class look like ?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class QPerson implements PersistableExpression&lt;Person&gt; &lt;br /&gt;{&lt;br /&gt;    public static final QPerson person = new QPerson("person");&lt;br /&gt;&lt;br /&gt;    public final QPerson bestFriend;&lt;br /&gt;    public final NumericExpression age;&lt;br /&gt;    public final StringExpression name;&lt;br /&gt;&lt;br /&gt;    ... (implementation of other PersistableExpression methods).&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;So in simple terms, we have a public field for each of the normal fields in Person, but that are of XXXExpression types. So when a user accessed QPerson.person they get the candidate for use in a query. Then they can do "person.name" and this is a StringExpression. The NumericExpressionImpl/StringExpressionImpl are the implementations for the particular provider of this typesafe query (e.g DataNucleus). You also notice above that the &lt;span style="font-style:italic;"&gt;bestFriend&lt;/span&gt; field is also a QPerson, and hence a PersistableExpression, so we can chain field access as "&lt;span style="font-style:italic;"&gt;person.bestFriend.firstName&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Methods of field types&lt;/h3&gt;&lt;br /&gt;Obviously in JDOQL (and Java), we allow some method calls. This is represented here by adding the supported methods to &lt;span style="font-style:italic;"&gt;StringExpression&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;NumericExpression&lt;/span&gt; etc. For example &lt;span style="font-style:italic;"&gt;StringExpression&lt;/span&gt; has a method &lt;span style="font-style:italic;"&gt;toUpperCase()&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt; to match what Java allows, so we can upgrade the query example to be&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;QPerson person = QPerson.person;&lt;br /&gt;Query&amp;lt;Person&amp;gt; q = pm.newTypesafeQuery(person);&lt;br /&gt;Person bob = &lt;br /&gt;    q.filter(person.firstName.toUpperCase().eq("BOB")).executeUnique();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There are still some more challenging areas of the API to work out, but the above is just to give a further taster and provoke comment.&lt;br /&gt;&lt;br /&gt;Please refer to the current javadocs &lt;a href="http://www.datanucleus.org/javadocs/core/2.2/org/datanucleus/query/typesafe/package-summary.html"&gt;here&lt;/a&gt; (Work-in-progress).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5716630360151639549?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5716630360151639549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/07/jdo-typesafe-refactorable-queries.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5716630360151639549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5716630360151639549'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/07/jdo-typesafe-refactorable-queries.html' title='JDO Typesafe Queries : Part 2 - Expressions'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-508225899593188854</id><published>2010-06-22T07:29:00.000-07:00</published><updated>2010-06-22T09:08:18.390-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><title type='text'>JDO Typesafe Refactorable Queries</title><content type='html'>One of the primary drawbacks with current JDO queries is that they are string-based, so you are hardcoding field names etc. When you refactor a (model) class, the field names are left unchanged, so the query no longer works. Some efforts have been made to simplify this process by providing a form of type-safe query (called &lt;span style="font-style:italic;"&gt;"criteria"&lt;/span&gt; queries by some, but the name is misleading since all queries define criteria) - see JPA2 Criteria queries, and also &lt;a href="http://source.mysema.com/display/querydsl/Querydsl"&gt;QueryDSL&lt;/a&gt;. Of the current offerings the QueryDSL fluent API approach is considered by many to be the most elegant.&lt;br /&gt;&lt;br /&gt;JDO needs such a type-safe refactorable query API. However it is important that this does not go down the track followed by JPA Criteria queries (IMHO) since it leads to excessive code just to generate a query, hence the fluent approach make more sense. What we are proposing would be something similar to the following (taken from QueryDSL, but adapted to use more JDOQL-like syntax)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;QCustomer customer = QCustomer.customer;&lt;br /&gt;Query&amp;lt;Customer&amp;gt; q = pm.newTypesafeQuery(customer);&lt;br /&gt;Customer bob = q.filter(customer.firstName.eq("Bob"))&lt;br /&gt;     .unique(true).execute();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;where the QCustomer class is generated automatically (during compilation via an annotation processor, or optionally via a separate process when not using JDO annotations).&lt;br /&gt;&lt;br /&gt;The idea is to provide support for all JDOQL syntax via this API, yet provide type-safe handling and refactorability, introducing this in the DataNucleus AccessPlatform 2.2 timeframe, and finally to standardise something similar into JDO 3.1. Your ideas/comments are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-508225899593188854?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/508225899593188854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/06/jdo-typesafe-refactorable-queries.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/508225899593188854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/508225899593188854'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/06/jdo-typesafe-refactorable-queries.html' title='JDO Typesafe Refactorable Queries'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-6658593265344678797</id><published>2010-06-03T05:36:00.000-07:00</published><updated>2010-06-18T03:28:24.406-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Persisting multisets (bags) with DataNucleus</title><content type='html'>A &lt;span style="font-style:italic;"&gt;multiset&lt;/span&gt; is a set where you can have a particular object multiple times in the set (a normal java.util Set will remove dups). This is also known by some as a "bag". &lt;a href="http://code.google.com/p/google-collections/"&gt;Google's Collections library&lt;/a&gt; has such a container class (&lt;i&gt;Multiset&lt;/i&gt;), and fields of this type are now persistable using DataNucleus.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Put the &lt;b&gt;datanucleus-googlecollections&lt;/b&gt; plugin in the CLASSPATH&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Develop your model using the Multiset java type.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Make sure that your Multiset field uses a join-table when persisting to RDBMS, and that the join-table doesn't have a primary-key defined&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;So if we have&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@PersistenceCapable&lt;br /&gt;public class Sample&lt;br /&gt;{&lt;br /&gt;    @Join(extensions=&lt;br /&gt;      @Extension(vendorName="datanucleus", &lt;br /&gt;            key="primary-key", value="false"))&lt;br /&gt;    Multiset&lt;Element&gt; elements = null;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;this will create an RDBMS join table as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE SAMPLE_ELEMENTS &lt;br /&gt;(&lt;br /&gt;    ID_OID BIGINT NOT NULL, &lt;br /&gt;    ID_EID BIGINT NOT NULL&lt;br /&gt;);&lt;/pre&gt;&lt;br /&gt;i.e no primary key, and so we can have duplicates of the same element in the Multiset.&lt;br /&gt;Thereafter the persistence just performs as normal (for JDO or JPA).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-6658593265344678797?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/6658593265344678797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/06/persisting-multisets-bags-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/6658593265344678797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/6658593265344678797'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/06/persisting-multisets-bags-with.html' title='Persisting multisets (bags) with DataNucleus'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-4238194568091072477</id><published>2010-04-16T08:16:00.001-07:00</published><updated>2010-06-22T11:27:33.668-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JCP'/><category scheme='http://www.blogger.com/atom/ns#' term='TCK'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>JPA, and the role of compliance</title><content type='html'>For some time we've been trying to get our hands on the JPA2 TCK (JSR317). This is a suite of tests that is supposed to define if your JPA implementation is "compliant". JPA (1, 2) are developed in private (secret) by the JCP. You can try to get on their "Expert Group" but since JPA1 did not allow in "just anybody" (and people were hand-picked in those days), there seems little point in participating in that.&lt;br /&gt;&lt;br /&gt;To actually get your hands on the "TCK" for any JSR you need to sign some form and send it to Sun/Oracle by snail mail. Since I sent one of these forms in (for the JPA1 TCK) back in 2007 then it really ought not to be necessary one would think. Well that's what we were advised by SUN/Oracle also (after a wait of a month and half). So here we are more than 2 months on and still no TCK. Not even a sniff of one.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why is this TCK so secret ?&lt;/span&gt;&lt;br /&gt;This seems a reasonable question. What is so sensitive in it that it shouldn't be open to everyone ? After all, with an open TCK, anybody would be able to actually test the implementation of their choice and verify if it is indeed compliant. They would also be able to view the testcases and contribute new ones that were missed in the test suite to cover other functionality. Obviously not everyone would want to download it and check people's claims, but then some would and it would hold people's claims up for review, unlike now. Really, why do I have to sign an NDA just to see it ? and why can't I publish the results in full on our website ?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why does it take so long ?&lt;/span&gt;&lt;br /&gt;Now granted SUN is merging into Oracle, but really 2+ months doesn't really seem too efficient. Why is the process manual, snail-mail driven ? After all, this is something electronic at the end of the day, so you would have expected that if people really have to apply for something then there would be a page on which to request it, and it would forward the infos to some team who approve or otherwise. Is this something typical of US organisations in general, or just Oracle?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why can other implementations claim compliance when we can't even get a chance to verify it?&lt;/span&gt;&lt;br /&gt;Really does say a lot about the corporate-driven JCP and politics. The JCP is inefficient, secretive, and doesn't present a level playing field for all.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS1. When I tried to get the JPA1 TCK back in 2007 it took 3 months of continual emailing before I finally got my hands on it. That was when they weren't merging with anyone else, so seems to be fairly typical of the wasteful process they have.&lt;br /&gt;&lt;br /&gt;PS2. JDO obviously has an open TCK, Apache2 licensed, available for all to download and contribute to. You don't need to sign NDA's just to see it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update (22nd June 2010) : Now more than 4 and a half months have passed since the original request for the JPA2 TCK. Still nothing.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So do you think Oracle is deliberately delaying this ? or is it just inefficient and disorganised ? Answers on a postcard please. The point that is becoming clearer is that JPA "compliance" is not worth the effort and DataNucleus releases will go forward claiming compliance since the JCP is preventing us from participating in this little game of theirs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-4238194568091072477?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/4238194568091072477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/04/jpa-and-role-of-compliance.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4238194568091072477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4238194568091072477'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/04/jpa-and-role-of-compliance.html' title='JPA, and the role of compliance'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5699233647565474665</id><published>2010-03-04T02:02:00.000-08:00</published><updated>2010-03-05T09:47:35.680-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><title type='text'>JDOQL2 status</title><content type='html'>Some time ago I started a new implementation of JDOQL for RDBMS, to replace the legacy (TJDO) JDOQL implementation. The legacy implementation had problems with generation of SQL for many queries, particularly involving "contains", "!contains" and use of unbound variables. As described &lt;a href="http://datanucleus.blogspot.com/2009/02/jdoql2.html"&gt;here&lt;/a&gt; the replacement implementation builds on the generic query compilation used for all other datastores.&lt;br /&gt;&lt;br /&gt;With the release of AccessPlatform 2.0.2 "JDOQL2" is ready for use in the vast majority of situations. It fixes various issues with the legacy implementation, successfully generating SQL for many queries that failed with legacy. It still doesn't compile every complicated query perfectly, but it is at least understood what parts it is failing on now, and none of those parts in general work in the legacy implementation.&lt;br /&gt;&lt;br /&gt;In AccessPlatform 2.1 "JDOQL2" will be renamed to "JDOQL", and the legacy implementation will become "JDOQL-Legacy" so you will get this new implementation by default, and have to explicitly select the legacy implementation if you wish to use it.&lt;br /&gt;&lt;br /&gt;By AccessPlatform 2.2 we intend to remove the legacy JDOQL and just move forwards with this new implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5699233647565474665?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5699233647565474665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/03/jdoql2-status.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5699233647565474665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5699233647565474665'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/03/jdoql2-status.html' title='JDOQL2 status'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5678371756739402689</id><published>2010-01-28T00:08:00.000-08:00</published><updated>2010-06-08T08:04:24.921-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='AppEngine'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>GAE/J and JDO/JPA</title><content type='html'>In April 2009 Google announced AppEngine for Java, providing support for JDO and JPA. Since that time people have had the chance to see what they think of it and identify shortcomings. This has lead to many misconceptions of JDO and JPA (though mainly JDO) due to thinking that what Google provide is a full and true representation of these standards; &lt;span style="font-style:italic;"&gt;it isn't&lt;/span&gt;. This blog entry attempts to correct some of these misconceptions, and to suggest some areas where Google could remedy the situation. All of the following items would help in providing a true reflection of these persistence standards and aid GAE/J users in having (much more) portable applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JDO/JPA : Lack of support for many methods and operators in JDOQL/JPQL&lt;/h2&gt;&lt;br /&gt;GAE/J only supports a relatively small subset of the available methods and operators of JDOQL/JPQL. This is due to the underlying datastore not supporting certain capabilities in its queryability. The problem is that this gives the impression that JDOQL/JPQL are somehow weak. What would make way more sense would be to evaluate all that is evaluatable in the datastore, and then have a flag set while compiling for whether the query contains any feature that the datastore query cannot handle and, if so, run the &lt;span style="font-style:italic;"&gt;DataNucleus in-memory query evaluator&lt;/span&gt; on the resultant instances. This would provide a transparent interface to JDOQL/JPQL and mean that people don't have to have build some custom queries just to get around GAE/J shortcomings.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JDO : No support for input candidate collection for JDOQL&lt;/h2&gt;&lt;br /&gt;GAE/J does not support inputting a candidate collection and query over that collection. This is a trivial thing to support, particular since the code necessary to do it was &lt;a href="http://code.google.com/p/datanucleus-appengine/issues/detail?id=155&amp;colspec=ID%20Stars%20Type%20Status%20Priority%20FoundIn%20TargetRelease%20Owner%20Summary"&gt;contributed&lt;/a&gt; some time ago, yet isn't in the current plugin.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JDO : pm.getExtent doesn't handle subclasses&lt;/h2&gt;&lt;br /&gt;The current pm.getExtent() implementation in GAE/J doesn't support the subclasses flag. The root cause is that the underlying datastore doesn't support a single query to retrieve a class and its subclasses. The simple solution would be to run "n" queries on the datastore, one for each of the possible subclass types, and merge the results. This would be simple to do and implement, and would provide correct JDO behaviour so users don't see any shortcoming.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JDO/JPA : exposing Google-specific id classes&lt;/h2&gt;&lt;br /&gt;With GAE/J there is some flexibility on what is allowable as a PK field; Long, String, and "Key". The first two are standard classes and standard JDO. The latter is environment specific. Firstly GAE/J ought to allow short/int/Short/Integer/long for true JDO/JPA operation so that users see no difference. Secondly, the "id" exposed to the user should be a JDO or JPA id and should be portable. When we implemented support for persisting to db4o we didn't expose db4o's id, instead wrapping it internally, so the user has no unexpected classes popping up that prevent their migration elsewhere later on.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JDO/JPA : one entity group per transaction&lt;/h2&gt;&lt;br /&gt;With GAE/J you have a restriction on the number of "entity groups" that can be enlisted in any transaction. Ok, but why expose this to the user and restrict what they do ? The logical way to do it would be to have multiple "internal" transactions for a JDO/JPA transaction and have each of these for a particular entity group. Since the underlying datastore doesn't provide ACID transactions anyway there is little impact of doing this. It would then mean that you don't impose on users having to split their persistence code apart just to get it to run, and hence mean that it is portable&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Unowned relations&lt;/h2&gt;&lt;br /&gt;This term is being used in GAE/J seemingly where you have a Collection&amp;lt;id&amp;gt; and so no real relation, although the "id" relate to other objects. This is perfectly representable in JDO/JPA as a Collection&amp;lt;long&amp;gt;, or Collection&amp;lt;String&amp;gt; or even Collection&amp;lt;Object&amp;gt;. With one of these "relations" the onus is on the user to manage the relation.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Support for types persistable as String&lt;/h2&gt;&lt;br /&gt;DataNucleus has, for some time, provided a mechanism for defining how to persist a type as a String (and retrieve its value from the String) - see ObjectStringConverter in DataNucleus "core" code. GAE/J could easily provide support for this in their plugin (if a type is not natively supported then check if there is an ObjectStringConverter and use that) and this would mean that many more Java types are persistable using AppEngine.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Documentation : @Persistent&lt;/h2&gt;&lt;br /&gt;In the GAE/J docs, every field has @Persistent marked against it. This is totally unnecessary, and you only need @Persistent for a non-standard field type. It leads to people believing that you must specify this to get something persisted, and so when they want to have a field not persisted they just remove the annotation. Please update the docs to reflect the minimal configuration required so we give a fair reflection of JDO and its spec. For example&lt;br /&gt;&lt;blockquote&gt;@PersistenceCapable&lt;br /&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;    @PrimaryKey&lt;br /&gt;    Long id;&lt;br /&gt;&lt;br /&gt;    String name;&lt;br /&gt;&lt;br /&gt;    double value;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Package naming "org.datanucleus.*"&lt;/h2&gt;&lt;br /&gt;This plugin is provided by Google not DataNucleus. It's currently packaged as "org.datanucleus.store.appengine". This leads to people believing that DataNucleus itself is at fault for its shortcomings. This is unacceptable and we own the domains &lt;span style="font-style:italic;"&gt;datanucleus.org&lt;/span&gt;/&lt;span style="font-style:italic;"&gt;datanucleus.com&lt;/span&gt;. Please rename your packages ASAP.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Nowhere have we seen any attribute of the GAE/J BigTable datastore that cannot be handled by the JDO or JPA API's. The JDO API (and metadata) in particular was designed as generic, and there is nothing in a "NoSQL" datastore that should cause it any problems with representation. We challenge anyone to define where there is such a problem area and it can then be addressed (there's a JIRA open on the Apache JDO project for just this situation); if you really can come up with a problem area then its in all of our interests to understand it and tackle it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5678371756739402689?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5678371756739402689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/01/gaej-and-jdojpa.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5678371756739402689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5678371756739402689'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/01/gaej-and-jdojpa.html' title='GAE/J and JDO/JPA'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-2426731302383369321</id><published>2010-01-08T03:50:00.000-08:00</published><updated>2010-03-05T09:48:30.265-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AccessPlatform'/><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>AccessPlatform 2.0 is released</title><content type='html'>a day ahead of schedule! Many internal APIs have changed so if making use of DataNucleus classes be prepared to update your code before using this release. The migration guide can be found &lt;a href="http://www.datanucleus.org/products/accessplatform/migration.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As ever, report any issues found in this release in the forum, and via JIRA (with testcase following the DN standard reproducing the issue).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-2426731302383369321?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/2426731302383369321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/01/accessplatform-20-is-released.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/2426731302383369321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/2426731302383369321'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/01/accessplatform-20-is-released.html' title='AccessPlatform 2.0 is released'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-1165724406267841057</id><published>2010-01-01T12:25:00.000-08:00</published><updated>2010-01-04T06:28:02.287-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='DataNucleus'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>AccessPlatform 2.0 will arrive soon</title><content type='html'>... just until the 9th January 2010 to wait. The result of 10 months of restructuring and extensions to DataNucleus, extending the capabilities and simplifying the process of adding on new datastore support for many things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-1165724406267841057?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/1165724406267841057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2010/01/access-platform-20-will-arrive-soon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/1165724406267841057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/1165724406267841057'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2010/01/access-platform-20-will-arrive-soon.html' title='AccessPlatform 2.0 will arrive soon'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-4490846701984390030</id><published>2009-11-19T06:34:00.000-08:00</published><updated>2009-11-20T08:00:07.607-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='primary-key'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Auto-generation of primary-key classes</title><content type='html'>The JDO spec defines a series of PK classes that will be used when you have a single primary-key field and don't specify the &lt;span style="font-style:italic;"&gt;objectidClass&lt;/span&gt;. This provides for the majority of situations meaning that the user can omit this time-consuming process of creating a PK class. Obviously this leaves the cases where you have more than 1 primary-key field. There are too many possible combinations of field types to be able to provide a series of PK classes as part of JDO, hence why this has always been an activity best handled by the user.&lt;br /&gt;&lt;br /&gt;DataNucleus AccessPlatform 2.0 now has an option on the &lt;a href="http://www.datanucleus.org/products/accessplatform_2_0/enhancer.html"&gt;byte-code enhancer&lt;/a&gt; to auto-generate a primary key class when enhancing the class itself; it is turned on by default (you can turn it off using the option "generatePK", setting it to false) and whenever the class has more than 1 PK field and has no &lt;span style="font-style:italic;"&gt;objectidClass&lt;/span&gt; defined it will generate a PK class file. The generated PK follows &lt;a href="http://www.datanucleus.org/products/accessplatform_2_0/jdo/primary_key.html"&gt;all JDO rules on PK classes&lt;/a&gt;, implementing Serializable, having public fields with the same names as the class PK fields, String constructor that can process the String created by the toString() method, etc. &lt;br /&gt;&lt;br /&gt;Note that this mode of the enhancer doesn't generate the Java file, just the class file, meaning that you don't have the overhead of having to manage the PK class once created - it will be created whenever you enhance the class in question.&lt;br /&gt;&lt;br /&gt;Give it a try and see what you find. It's been tested on simple cases only so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-4490846701984390030?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/4490846701984390030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2009/11/auto-generation-of-primary-key-classes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4490846701984390030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4490846701984390030'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2009/11/auto-generation-of-primary-key-classes.html' title='Auto-generation of primary-key classes'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-435935060926865913</id><published>2009-11-06T04:16:00.000-08:00</published><updated>2009-11-06T07:40:24.692-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataNucleus'/><category scheme='http://www.blogger.com/atom/ns#' term='JPQL'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>"JPQL2" becomes the default JPQL implementation for RDBMS</title><content type='html'>The rewrite of JPQL for RDBMS, formerly known as "JPQL2" is now the default JPQL implementation in DataNucleus SVN trunk. It passes the JPA TCK completely, and so no reason not to swap over to using it now. So if you want to use the old (legacy) implementation of JPQL for RDBMS you must define the implementation &lt;br /&gt;&lt;pre&gt;datanucleus.query.JPQL.implementation=JPQL-Legacy&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's likely that there are some combinations of expressions that still need adding but provides a good basis for JPA querying.&lt;br /&gt;&lt;br /&gt;The reason that JDOQL2 is not yet the default is that JDOQL requires support for variables to define joins, whereas JPQL has explicit joins defined in its syntax, hence it was easier to provide JPQL. Hopefully JDOQL2 won't be too far behind. Report any problems with this implementation of JPQL using JIRA for project "NUCRDBMS".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-435935060926865913?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/435935060926865913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2009/11/jpql2-becomes-default.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/435935060926865913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/435935060926865913'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2009/11/jpql2-becomes-default.html' title='&quot;JPQL2&quot; becomes the default JPQL implementation for RDBMS'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-4649684693922292678</id><published>2009-04-30T08:50:00.000-07:00</published><updated>2009-05-01T03:20:42.048-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='DataNucleus'/><category scheme='http://www.blogger.com/atom/ns#' term='JPQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>"JPQL2"</title><content type='html'>As mentioned &lt;a href="http://datanucleus.blogspot.com/2009/02/jdoql2.html"&gt;earlier&lt;/a&gt; DataNucleus querying capabilities are being progressively rewritten, making use of a &lt;span style="font-style:italic;"&gt;"generic" query compilation&lt;/span&gt;. In the previous post I mentioned a new implementation of JDOQL. This now implements the vast majority of querying capabilities required with one exception ... &lt;span style="font-weight:bold;"&gt;variables&lt;/span&gt; (to be added soon hopefully). In addition, for this RDBMS implementation, you can evaluate queries&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Totally in the datastore.&lt;/li&gt;&lt;li&gt;Totally in-memory (you supply the candidate instances, and it queries over those instances).&lt;/li&gt;&lt;li&gt;Retrieve all candidates from the datastore, and evaluate the filter, result etc in memory.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;SVN trunk now has a new addition following the same basic idea ... "JPQL2". This implements JPQL using the same underlying SQL API, and using the bulk of the new code added for "JDOQL2". Since JPQL doesn't support variables then this implementation is close to complete (with the exception of bulk update/delete - to be added soon).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;One important feature to note is that a user can contribute their own implementation of various methods, or functions by adding their own plugin (just a single method typically). See &lt;a href="http://www.datanucleus.org/products/accessplatform_1_1/extensions/sql_methods.html"&gt;the docs&lt;/a&gt; for an example.&lt;/p&gt;&lt;p&gt;The intention is to make these new implementations the default in the next major release of DataNucleus Access Platform. To try them out add the following persistence properties&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;datanucleus.query.JDOQL.implementation=JDOQL2&lt;br /&gt;datanucleus.query.JPQL.implementation=JPQL2&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-4649684693922292678?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/4649684693922292678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2009/04/jpql2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4649684693922292678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/4649684693922292678'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2009/04/jpql2.html' title='&quot;JPQL2&quot;'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-8482584726457330678</id><published>2009-02-18T05:35:00.000-08:00</published><updated>2009-11-20T05:38:29.977-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='DataNucleus'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JDOQL'/><title type='text'>"JDOQL2"</title><content type='html'>DataNucleus started out as JPOX, which started as TJDO. This had support for RDBMS, and in particular JDOQL querying. Unfortunately the TJDO process for JDOQL was a sequential parse of the query string, generating the SQL for the query. While we extended this a lot during the JPOX lifetime this was always limited by the underlying API available and the process (not being able to easily inspect the query to see if something has AND or OR at the same level, and hence decide if we should do an EXISTS, or an INNER JOIN etc etc). It was always planned to rewrite it at some point, particularly to make the query compilation available to other types of datastores, but also to try to resolve some of the problems.&lt;br /&gt;&lt;br /&gt;DataNucleus AccessPlatform 1.1 now has a &lt;span style="font-weight: bold;"&gt;generic query compilation process&lt;/span&gt; (proof of concept written by Erik, and extended by me to come close to complete compilation, with some minor patch contributions from others). The generic query compilation results in expression "trees" for each component of the query; these are easier to analyse and hence to generate any native query from, for the datastore being used. This generic query compilation is what is used by all datastore plugins (with the exception of legacy RDBMS). In addition it includes an &lt;span style="font-weight: bold;"&gt;"in-memory" query evaluator&lt;/span&gt;. This is intended to take in a collection of candidates for the query, and evaluate the filter clause using the data in those instances. This in-memory evaluation works for many things but currently doesn't yet support Collection.contains, Map.containsKey, etc and also variables.&lt;br /&gt;&lt;br /&gt;AccessPlatform 1.1 RDBMS plugin also includes code for something referred to as &lt;span style="font-weight: bold;"&gt;"JDOQL2"&lt;/span&gt;. This is not a new query language, but instead an alternative implementation of JDOQL for RDBMS datastores. It uses the underlying generic query compilation (like for the other datastores), and has a step converting this into SQL. This new implementation has a few key concepts&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Uses a newly written &lt;span style="font-weight: bold;"&gt;SQL API&lt;/span&gt; to generate the statement&lt;/li&gt;&lt;br /&gt;&lt;li&gt;SQL statement strings are JDBC-compatible, having parameters only where the user query has them (TJDO SQL didn't follow this)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Users have control over the naming scheme for table aliases in the SQL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implementation of support for &lt;span style="font-weight: bold;"&gt;JDOQL "methods" via a plugin-point&lt;/span&gt;, so you could write a plugin for &lt;i&gt;Collection.size()&lt;/i&gt;, for example, if you wanted.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Support is provided for all aggregate functions, the main String methods, the main Date methods, JDOHelper.getObjectId, Collection.size(), Collection.isEmpty(), Map.size(), Map.isEmpty(), and some others ... but not yet Collection.contains/Map.containsKey/Map.containsValue/Map.get&lt;/li&gt;&lt;br /&gt;&lt;li&gt;All queries compiled using JDOQL2 are cached, meaning they are not compiled again for that PMF&lt;/li&gt;&lt;br /&gt;&lt;li&gt;With the legacy JDOQL implementation, a query would be compiled at execute (and also at compile if compile() was called). In JDOQL2 it is only compiled once.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;JDOQL2 implements the &lt;span style="font-weight: bold;"&gt;JDO2.3 query timeout/cancel API&lt;/span&gt;, so you can, in principle, cancel queries if they were submitted from a different thread and are still running. This would then cancel the underlying JDBC query (assuming the JDBC driver supports it)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Queries will retrieve not just non relation fields (like with legacy JDOQL) but also any 1-1 fields, hence avoiding the "1+N" problem&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;JDOQL2 is there for you to use and try, just do something like (for RDBMS)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Query q = pm.newQuery("JDOQL2",&lt;br /&gt;   "SELECT FROM mydomain.MyClass WHERE field1 &lt; :param");&lt;br /&gt;q.execute(value); &lt;/pre&gt;&lt;br /&gt;and see what you find. The idea is that this will replace (legacy) JDOQL for RDBMS sometime in the AccessPlatform 2.0 lifecycle; maybe not if time doesn't allow it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-8482584726457330678?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/8482584726457330678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2009/02/jdoql2.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8482584726457330678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/8482584726457330678'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2009/02/jdoql2.html' title='&quot;JDOQL2&quot;'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-7625766372307764372</id><published>2009-01-27T02:32:00.001-08:00</published><updated>2009-01-28T03:43:28.252-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='DataNucleus'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>JDO 2.3 Metadata API</title><content type='html'>Defining how classes are to be persisted has always been a subjective part of any persistence process. Some people like XML, some like annotations, and some want it all to be done magically with a sprinkle of stardust. JDO has always allowed configuration using XML. In JDO 2.1 we introduced the ability to use annotations (and a mix of annotations and XML). With JDO 2.3 we're introducing a third way ... via an API. Let's assume we have a class we want to persist&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;public class Client&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    String name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    ...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The basic idea is as follows. We want to define the metadata programmatically for our class&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(propsFile);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;JDOMetadata md = pmf.newMetadata();&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So our PMF has created a new metadata object to work with. This corresponds to the top level of a metadata file. We can now add packages and classes as required to define the persistence. So something like this ...&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;PackageMetadata pmd = md.newPackageMetadata("org.datanucleus");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;so we have a package for our class. Now let's define the persistence of the class :-&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;ClassMetadata cmd = pmd.newClassMetadata("Client");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cmd.setTable("CLIENT").setDetachable(true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cmd.setIdentityType(IdentityType.DATASTORE);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cmd.setPersistenceModifier(ClassPersistenceModifier.PERSISTENCE_CAPABLE);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and the class needs persistence for the field "name" defining (since we don't want to accept default persistence specifications) :-&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;FieldMetadata fmd = cmd.newFieldMetadata("name");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;fmd.setNullValue(NullValue.DEFAULT).setColumn("client_name");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;fmd.setIndexed(true).setUnique(true);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and of course we can define everything else as required, so to persist it into its own table, and to have versioning, etc :-&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;InheritanceMetadata inhmd = cmd.newInheritanceMetadata();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;inhmd.setStrategy(InheritanceStrategy.NEW_TABLE);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DiscriminatorMetadata dmd = inhmd.newDiscriminatorMetadata();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;dmd.setColumn("disc").setValue("Client");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;dmd.setStrategy(DiscriminatorStrategy.VALUE_MAP).setIndexed(Indexed.TRUE);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VersionMetadata vermd = cmd.newVersionMetadata();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;vermd.setStrategy(VersionStrategy.VERSION_NUMBER);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;vermd.setColumn("version").setIndexed(Indexed.TRUE);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All that remains to do is enable this metadata in our persistence process&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;pmf.registerMetadata(md);&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Key points :&lt;ul&gt;&lt;br /&gt;&lt;li&gt;you get your starting object (JDOMetadata) from the PMF.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;you only need to add fields and attributes that are non-defaulted. As with a metadata file, all fields of standard types are by default persistent&lt;/li&gt;&lt;br /&gt;&lt;li&gt;you can chain mutator operations. I've split them above for readability, but they could have been on a single line.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;once populated you register the start object with the PMF. Thereafter when that class is used in persistence it will use that metadata definition.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If a class is already known to the PMF (has its file-based metadata registered) then you can't redefine it using this API.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The logical next step is to be able to view the metadata defined in XML or annotations. You can do this as follows&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;ComponentMetadata compmd = pmf.getMetadata("mydomain.MyClass");&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and you can now interrogate the metadata of this class (cast it to &lt;span style="font-style: italic;"&gt;ClassMetadata&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;InterfaceMetadata&lt;/span&gt;). Please note that it is not supported being able to change metadata that is already registered, just view it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Final point worth making is that the DataNucleus implementation of these metadata classes will output the (approximate) XML text representation when you call &lt;span style="font-style: italic;"&gt;"toString()"&lt;/span&gt; on the metadata object, so for example the metadata generation above results in&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&amp;lt;jdo&amp;gt;&lt;br /&gt;  &amp;lt;package name="org.datanucleus"&amp;gt;&lt;br /&gt;     &amp;lt;class name="Client" type="datastore" modifier="persistence-capable" table="CLIENT" detachable="true"&amp;gt;&lt;br /&gt;         &amp;lt;inheritance strategy="new-table"&amp;gt;&lt;br /&gt;             &amp;lt;discriminator strategy="value-map" column="disc" value="Client" indexed="true"&amp;gt;&lt;br /&gt;             &amp;lt;/discriminator&amp;gt;&lt;br /&gt;         &amp;lt;/inheritance&amp;gt;&lt;br /&gt;         &amp;lt;version strategy="version-number" indexed="true" column="version"&amp;gt;&lt;br /&gt;         &amp;lt;/version&amp;gt;&lt;br /&gt;         &amp;lt;field name="name" column="client_name" indexed="true" unique="true"&amp;gt;&lt;br /&gt;         &amp;lt;/field&amp;gt;&lt;br /&gt;     &amp;lt;/class&amp;gt;&lt;br /&gt; &amp;lt;/package&amp;gt;&lt;br /&gt;&amp;lt;/jdo&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;so you also have an easy way of converting your API generated metadata into XML should you wish to transfer it to a file for later use.&lt;br /&gt;&lt;br /&gt;This is now in DataNucleus SVN trunk. You need the latest Apache JDO API jar (also in DataNucleus SVN, and in the nightly build repositories).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-7625766372307764372?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/7625766372307764372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2009/01/jdo-23-metadata-api.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/7625766372307764372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/7625766372307764372'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2009/01/jdo-23-metadata-api.html' title='JDO 2.3 Metadata API'/><author><name>andy</name><uri>http://www.blogger.com/profile/17533997034317556391</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_sEclcGXdnrA/SWdgMGXD_eI/AAAAAAAAADA/acCwJGbA7lE/S220/pic_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1936942592343397099.post-5553722811082272482</id><published>2008-10-04T11:28:00.001-07:00</published><updated>2010-01-04T06:28:50.984-08:00</updated><title type='text'>Welcome to the DataNucleus</title><content type='html'>DataNucleus is a project providing Open Source software for use in the Java language, for persisting objects to datastores.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.datanucleus.org/products/accessplatform_1_0.html"&gt;DataNucleus AccessPlatform 1.0 (Faraday)&lt;/a&gt; was released on September 1st 2008, providing JDO/JPA persistence to RDBMS, db4o, XML, Excel, LDAP, NeoDatis and JSON datastores.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.datanucleus.org/products/accessplatform_1_1.html"&gt;DataNucleus AccessPlatform 1.1 (Rutherford)&lt;/a&gt; development started soon after and will build on the support in 1.0, aiming at migrating the RDBMS query support to use the new generic query mechanism, as well as moving to a JDK 1.5+ environment.&lt;br /&gt;&lt;br /&gt;As with the majority of Open Source software, DataNucleus is freely downloadable. Limited amounts of free support is available by our &lt;a href="http://forum.datanucleus.org/"&gt;forum&lt;/a&gt;. We do also provide &lt;a href="http://www.datanucleus.com/services/support.html"&gt;commercial support&lt;/a&gt;, and by purchasing this you are keeping the project going.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1936942592343397099-5553722811082272482?l=datanucleus.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://datanucleus.blogspot.com/feeds/5553722811082272482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://datanucleus.blogspot.com/2008/10/welcome.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5553722811082272482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1936942592343397099/posts/default/5553722811082272482'/><link rel='alternate' type='text/html' href='http://datanucleus.blogspot.com/2008/10/welcome.html' title='Welcome to the DataNucleus'/><author><name>Data Nucleus</name><uri>http://www.blogger.com/profile/06897027554521041521</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://3.bp.blogspot.com/_oe9VRBj6u4E/SOe0z_TK4KI/AAAAAAAAAA0/5zjy0zmifUk/S220/DN.jpg'/></author><thr:total>0</thr:total></entry></feed>
