Can Hibernate OGM Persistence Provider be used with Spring-data-jpa? - spring-data

I really like the simplicity of spring data repository, however need to use hibernate as persistence provider for consistency and few other factors. (I am using mongodb but not using mongo template). Few things I noticed --
The HibernateJpaVendorAdapter uses "org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider"
The provider configured with the persistence unit ( ""org.hibernate.ogm.jpa.HibernateOgmPersistence" ) is not considered, while constructing the EntityManagerFactory through a "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" bean.
If there are multiple persistence units configured for the project there is no apparent way to associate a persistence unit for a repository.
Questions:
Is there a way to use the configured persistence provider , instead of the default one ? The default provider is not working with mongodb.
Is there a way to associate a repository with a specific persistence unit ?

A partial solution was to
implement
org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter and
return an instance of
org.hibernate.ogm.jpa.HibernateOgmPersistence in
getPersistenceProvider() method
Source the jpaVendorAdapter property for entityManagerFactory
bean in spring config
However it still doesn't work good wherever there is reference to Pageable. Some design change can circumvent the issue.

Related

Spring Data JPA Repository CRUD Testing

I'm playing around with the Spring Data Repository and have a question on writing CRUD tests. I have written many CRUD tests against Hibernate DAOs and EJB 3 entity beans where I create and entity, flush it to the database, clear the entity manager, and read it back by ID. The entity manager is cleared so the first level cache is not hit on the read.
Using the Spring Data repository I can't find a way to clear the underlying entity manager used by my test so my read is not going back to the actual database, making my test invalid.
Is there any way to clear the entity manager in the test? Is there a way I can inject one into my test so that it is used by the repository?
Thanks!
Cory.
Try it by injecting the entitymanager like this:
#PersistenceContext
EntityManager entityManager
and make your test transactional by setting the #Transactional attribute on your test method. Then inside the method you can call the entityManager.flush() method.
Regards
If you wish the EntityManager to be cleared automatically you can set #Modifying annotation’s clearAutomatically attribute to true.
Please see here

How does Spring Data know wicht store to back a repository with if multiple modules are used?

In a Spring Data project if I am using multiple types of repositories i.e JPA repository and Mongo repository and if I am extending CrudRepository then how does Spring Data know which store to choose for that repository? It can use JPA or Mongo. Is it based on the annotation #Document or #Entity added on every persisting entity?
The decision which store a proxy created for a Spring Data repository interface is only made due to your configuration setup. Assume you have the following config:
#Configuration
#EnableJpaRepositories("com.acme.foo")
#EnableMongoRepositories("com.acme.foo")
class Config { }
This is going to blow up at some point as the interfaces in package com.acme.foo are both detected by the MongoDB and JPA infrastructure. To resolve this, both the JavaConfig and XML support allows you to define include and exclude filters so that you can either use naming conventions, additional annotations or the like:
#Configuration
#EnableJpaRepositories(basePackages = "com.acme.foo",
includeFilters = #Filter(JpaRepo.class))
#EnableMongoRepositories(base Packages = "com.acme.foo",
includeFilters = #Filter(MongoRepo.class))
class Config { }
In this case, the two annotations #JpaRepo and #MongoRepo (to be created by you) would be used to selectively trigger the detection by annotating the relevant repository interfaces with them.
A real auto-detection is sort of impossible as it's hard to tell which store you're targeting solely from the repository interface declaration and at the point in time when the bean definitions are created we don't even know about any further infrastructure (an EntityManager or the like) yet.

Why don't exceptions in spring-data-commons extend DataAccessException?

I'm trying to handle the Spring DAO Exceptions (http://docs.spring.io/spring/docs/4.0.3.RELEASE/spring-framework-reference/htmlsingle/#dao-exceptions) in the service layer of my application, just to discover that the exceptions in the spring-data-commons module don't extend org.springframework.dao.DataAccessException.DataAccessException.
Example: PropertyReferenceException.
As far as I can tell, all exceptions in this module, and maybe in the other sub-modules of Spring Data projects should extend DataAccessException.
Is there anything obvious that I'm not seeing here?
There is no need for Spring Data to use Spring Core's DataAccessException hierarchy as one may use the PersistenceExceptionTranslator. The latter translates thrown exceptions of e.g. Spring Data Repositories to a DataAccessException subtype.
PersistenceExceptionTranslator kicks in automatically when marking your repository with the "#Repository" annotation. The service (using the annotated repository) may catch the DataAccessException, if needed.

Accessing JPA Class Mapping

Found an article in springsource which describes how to manipulate the schema name at runtime.
http://forum.springsource.org/showthread.php?18715-changing-hibernate-schemas-at-runtime
We're using pure jpa however where were using a LocalContainerEntityManagerFactory and don't have access to Session or Conofiguration instances.
Can anyone provide insight on how to access the metadata at runtime (via the entitymanager) to allow modifying the schema?
Thanks
Changing meta-data at runtime is JPA provider specific. JPA allows you to pass a Map of provider specific properties when creating an EntityManagerFactory or EntityManager. JPA also allows you to unwrap() an EntityManager to a provider specific implementation.
If you are using EclipseLink you can set the schema using the setTableQualifier() API on the Session's login.
You can't using standard JPA (which is your requirement going by your question); it doesn't allow you to dynamically define metadata, only view (a limited amount of) specified metadata via its metamodel API. You'd have to delve into implementation specifics to get further, but then your portability goes down the toilet at that point, which isn't a good thing.
JDO, on the other hand, does allow you to dynamically define metadata (and hence schema) using standardised APIs.

compare two EntityManagerFactories for having PersistenceUnits with identical connection attributes

Having two JPA2 (EclipseLink) EntityManagerFactory instances what would be the best way to detect that their PersistenceUnit attributes are identical?
You can call getProperties() to get the persistence unit properties and compare them.
Normally EclipseLink will use the same EclipseLink ServerSession if the same persistence unit is used twice. You can call unwrap(Session.class) to get the session, and see if they are the same.
I think you're best hit would be to get (somehow, someway, ...) access to the PersistenceUnitInfo interface which is implemented and created by the container and passed to the JPA provider. The JPA provider uses it when creating the EntityManagerFactory.