1581 words

JPA vs JDO - which is more efficient for OneToMany queries?

#1
2010-11-09 12:04

I'm curious about the trade offs between JDO and JPA. Seems to me that JDO will perform better and be statically typed. For example: Assume there are Customers and Orders. with JDO I would do this:

@PersistenceCapable 
class Customer 
{       
  Vector <Order> orders; 
} 
class Order  
{ 
} 

Whereas with JPA I tend to do this:

@Entity 
class Customer 
{ 
} 
class Order 
{     
  Customer customer; 
} 

So, with the JDO version, to get the orders for a customer, I do this:

customer.getOrders ();

Whereas with JPA, I do this:

em.createQuery ("SELECT o FROM Order o WHERE o.customer="+c).getResultList(); 

QUESTION: Apart from the loss of static typing with the JPA version, is there a performance hit? ie: with the JDO version you have essentially an index from the Customer class to its Orders, while with the JPA version you have to query the database.

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #6
#2
2010-11-09 18:27

JPA and JDO have similar capabilities and the following definition is valid in JPA:

@Entity
class Customer 
{       
  @OneToMany // the annotation is not required by ObjectDB
  Vector<Order> orders; 
}
 
@Entity
class Order  
{ 
}

It is true, however, that in ORM-based implementations it is more efficient to use non collection references, to avoid a JOIN table (so a reference from Order to Customer in the above example is more efficient), but that is true for both JPA and JDO ORM-based implementations.

By the way, if you define the reference in Order, you can use an inverse / mapped-by field in Customer as demonstrated and explained at http://www.objectdb.com/java/jpa/entity/fields#Inverse_Fields. A query will still be executed (i.e. navigation from Customer to Order will run an automatic query), but your code will be cleaner.

When using ObjectDB, however, it is efficient to define the reference in either side. Therefore, the same definition above, which is less efficient in ORM-based implementation and requires a JOIN table and a query for navigation, is implemented differently in ObjectDB, because an entity in ObjectDB is not limited to a row structure and ObjectDB can store a collection of references embedded in an entity object.

The bottom line is that the difference is not between JPA and JDO but between ObjectDB and ORM-based implementations of JPA/JDO. ObjectDB supports one-to-many and many-to-many relationships more efficiently than ORM implementations.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #59
#3
2010-11-09 20:00

Thanks, I discovered the inefficiency in the ORM world (non-ObjectDB).

Maybe I should have restated the question:

For ObjectDb specifically, which is more efficient:

a) Use JDO with a collection reference (Customer.orders), or

b) Use JPA with an inverse reference (Order.customer) ?

If no performance difference, then JDO wins due to static typing, in my view.

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #8
#4
2010-11-09 21:04

It depends on what your application does, of course. But assuming that navigation is mostly from the customer to the orders, when using ObjectDB a collection reference (Customer.orders) is more efficient.

But why do you compare JDO (a) with JPA (b). It doesn't matter which API you use. So in the two options that you wrote you can replace JPA and JDO and JDO with JPA and the answer will still remain the same.

In addition, when you use (b) - you have references in both sides. The owner has ordinary reference and on the other side you define an inverse field, which is implemented by running a query (and has no real value in the database). Anyway, you will have strong static typing and you don't have to run queries yourself, also in this case.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #61
#5
2010-11-09 21:19

Ok, let me see if I grok this.

Using JPA:

@Entity
class Customer 
{
  @OneToMany(mappedBy="customer")
  Vector<Order> orders;
}
 
@Entity
class Order  
{
  @ManyToOne
  Customer customer
}

Are you saying that the Customer.orders field has no value in the database, yet I can find all the orders thus: customerX.orders () instead of: "SELECT o FROM Order o WHERE o.customer=customerX" Am I understanding this correctly?

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #10
#6
2010-11-09 21:24

Assuming I grok the above, questions:

1) Do I need to explicitly set both ends, ie:

customerX.orders.add (orderY);
 
orderY.customer = customerX;

or, can I just set:

orderY.customer = customerX, and the inverse is set automatically??

2) do I need to persist both customerX and orderY explicitly?

Sounds like you're generally arguing in favor of JPA.

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #11
#7
2010-11-09 21:27

1) The inverse field is set automatically, but only when you read the object that contains the inverse field (again) or refresh it.

2) You have to persist both unless you have automatic cascade persist. In JDO all fields cascade persist operations automatically. In JPA you have to set it per field or globally.

I am not arguing in favor of JPA, at least not on this thread, because I say they are feature equivalent. The FAQ discusses which API should be preferred.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #63
#8
2010-11-09 22:48

For JPA, how does one set automatic cascade globally? Seems useful for persist, delete, etc.

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #12
#9
2010-11-09 23:42
ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #64
#10
2010-11-10 03:01

wow - just tried it, pretty impressive.

I used JPA, and the @OneToMany(mappedBy="")

on the collection was handled entirely implicitly!

dmoshal
dmoshal's picture
Joined on 2010-05-22
User Post #13

Post Reply

Please read carefully the posting instructions - before posting to the ObjectDB website.

  • You may have to disable pop up blocking in order to use the toolbar (e.g. in Chrome).
  • Use ctrl + right click to open the browser context menu in the editing area (e.g. for using a browser spell checker).
  • To insert formatted lines (e.g. Java code, stack trace) - select a style in the toolbar and then insert the text in the new created block.
  • Avoid overflow of published source code examples by breaking long lines.
  • You may mark in paragraph code words (e.g. class names) with the code style (can be applied by ctrl + D).
  • Long stack traces (> 50 lines) and complex source examples (> 100 lines) should be posted as attachments.
Attachments:
Maximum file size: 32 MB
Cancel