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

#1

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.

#2

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 https://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
#3

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.

#4

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
#5

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?

#6

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.

#7

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
#8

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

#9
ObjectDB Support
#10

wow - just tried it, pretty impressive.

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

on the collection was handled entirely implicitly!

Reply