persistence
persistence copied to clipboard
Support for loading multiple entities by id
I propose the spec add the capability to load multiple entities by id at one time (multi-load).
Many use cases require loading multiple entities at once. Querying could definitely be an option.
EntityManager em = ...;
List<Product> products = em.createQuery( "select p from Product p where p.id in (:ids)", Product.class )
.setParameter( "ids", Arrays.asList( 1, 2, 3, 4 )
.getResultList();
However, that has a few drawbacks - the main one being potentially returning way too much data from the database when many ids are requested and a significant number of them are already managed in the EntityManager.
To really get this full capability with JPA today, a user would need to perform a complex series of calls. E.g.
EntityManager em = ...;
EntityManagerFactory emf = em.getFactory();
int[] ids = new int[] { 1, 2, 3, 4 }
List<Product> products = new ArrayList<>();
for ( Integer id : ids ) {
// see if it already exists...
// NOTE : overly simplistic...
Product existing = em.getReference( Product.class, id );
if ( emf.getPersistenceUnitUtil().isLoaded( existing ) ) {
products.add( existing );
}
else {
// we could get fancy here and collect the ids to load from db and issue one query,
// but lets do the simple thing here for illustration purposes
products.add( initializeProxy( product ) );
}
}
One option for API in JPA would be overloads of the existing #find methods (assuming we don't want multiple #getReference loading):
interface EntityManager {
...
// existing
<T> T find(Class<T> entityType, Object id);
<T> T find(Class<T> entityClass, Object id, LockModeType lockMode);
<T> T find(Class<T> entityClass, Object id, LockModeType lockMode, Map<String, Object> properties);
<T> T find(Class<T> entityClass, Object id, Map<String, Object> properties);
// additions
<T> List<T> find(Class<T> entityType, Object... ids);
<T> List<T> find(Class<T> entityClass, Map<String, Object> properties, Object... ids);
<T> List<T> find(Class<T> entityClass, LockModeType lockMode, Object... ids);
<T> List<T> find(Class<T> entityClass, LockModeType lockMode, Map<String, Object> properties, Object... ids);
}
Possibly accepting List of ids in addition to or instead of:
interface EntityManager {
...
<T> List<T> find(Class<T> entityType, List<?> ids);
<T> List<T> find(Class<T> entityClass, Map<String, Object> properties, List<?> ids);
<T> List<T> find(Class<T> entityClass, LockModeType lockMode, List<?> ids);
<T> List<T> find(Class<T> entityClass, LockModeType lockMode, Map<String, Object> properties, List<?> ids);
}
This capability almost made it into #383, but with the change of direction there, it's missed out.
Nevertheless, I think we should consider this feature for inclusion in JPA 3.2.