Integrating Hibernate OGM and Spring Data JPA - spring

How can we integrate Hibernate OGM with Spring Data JPA, so that existing application containing Hibernate ORM can be used with Hibernate OGM.
This is the configuration i'm currently using for Hibernate ORM
#Bean(name = "jdbc")
public DriverManagerDataSource getDriverManager() {
DriverManagerDataSource driverManagerDataSource = new
DriverManagerDataSource(
env.getProperty(dataBase + ".url"), env.getProperty(dataBase +
".username"),
env.getProperty(dataBase + ".password"));
driverManagerDataSource.setDriverClassName(env.getProperty(dataBase +
".driver"));
return driverManagerDataSource;
}
#Bean(name = "japaImplementation")
public HibernateJpaVendorAdapter getHibernate() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabasePlatform(env.getProperty(dataBase + ".dialect"));
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean
getEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean = new
LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(getDriverManager());
factoryBean.setJpaVendorAdapter(getHibernate());
factoryBean.setPackagesToScan("com.xyz.abc.entity");
return factoryBean;
}

I just had a quick glance at Hibernate OGM. It seems it is just a JPA implementation. So Spring Data JPA should work out of the box for it. Although up to now it does not get tested against it.
But it raises the question, why you would want to do that? There are already Spring Data modules for most, if not all of the data stores supported by Hibernate OGM. So why don't you use Spring Data MongoDB directly?

The projects are more alternatives to each other than something to let one run on top of the other. See this question for arguments from both sides.

Related

How can i connect to 2 different Schemas on one datasource in springboot

I am trying to extract data from multiple databases in different servers. This has been successful after configuring different Data sources as shown in my code however i cannot see to configure 2 different Data sources on the same connection.
I have tried to create 2 beans within the config file but i would still need to set the Data source.
#Configuration
#EnableJpaRepositories(basePackages = {"balances.Repository.World"},
entityManagerFactoryRef = "ASourceEntityManager",transactionManagerRef = "ASourceTransactionManager")
#EnableTransactionManagement
public class World{
#Autowired
private Environment env;
#Bean
public LocalContainerEntityManagerFactoryBean ASourceEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(ASourceDatasource());
em.setPackagesToScan(new String("balances.Repository.World"));
em.setPersistenceUnitName("ASourceEntityManager");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.dialect",env.getProperty("app.datasource.ASource.hibernate.dialect"));
properties.put("hibernate.show-sql",env.getProperty("app.datasource.ASource.show-sql"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
#ConfigurationProperties(prefix = "app.datasource.ASource")
public DataSource ASourceDatasource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("app.datasource.ASource.driverClassName"));
dataSource.setUrl(env.getProperty("app.datasource.ASource.url"));
dataSource.setUsername(env.getProperty("app.datasource.ASource.username"));
dataSource.setPassword(env.getProperty("app.datasource.ASource.password"));
return dataSource;
}
#ConfigurationProperties(prefix = "app.datasource.ASourceB")
public DataSource ASourceDatasource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("app.datasource.ASourceB.driverClassName"));
dataSource.setUrl(env.getProperty("app.datasource.ASourceB.url"));
dataSource.setUsername(env.getProperty("app.datasource.ASourceB.username"));
dataSource.setPassword(env.getProperty("app.datasource.ASourceB.password"));
return dataSource;
}
#Bean
public PlatformTransactionManager ASourceTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
ASourceEntityManager().getObject());
return transactionManager;
}
After some thought i have come up with a workaround that might be a bit hacky but gets the job done.
Instead of declaring a new database connection for the second schema in my app.properties i have used one connection. I placed all my entities in one model package and used a native query to access the other schema. In the native query i would then specify the schema eg:
select * from DATABASE1.Id;
This solution does not scale well as it would create a lot of work when dealing with a large number of entities so if there is a way of specifying the schema in the repository that would also help.
I tried using the entity attributes to define my schema but jpa seems to be ignoring it and prefixing the table with the wrong schema for example if
i annotate my class with the following
#Table(name = "Payment", schema = "DATABASE1", catalog = "")
The resulting query would be "select * from DATABASE2.Payment" instead of
select * from DATABASE1.Payment

Spring boot with apache OpenJPA

I am trying to integrate my test spring boot application with DB.
I don't want to use Hibernate vendor, I want to use apache OpenJPA.
My current bootstrap.yml looks like this
spring:
datasource:
url: jdbc:oracle:thin:#xxxx:1521:xxx
username: xxxx
password: xxxx
driver-class-name: oracle.jdbc.OracleDriver
Is it possible to set dialect to work with OpenJPA?
Does spring supports today OpenJpa?
If you could provide some example of configuration it would be great.
Thank in advance.
upd: In example founded here - configure openjpa on to spring boot I see that used OpenJpaVendorAdapter which does not exist in spring 5.
In documentation of spring-data https://docs.spring.io/spring-data/jpa/docs/current/reference/html/ said that
Spring Data JPA 1.10 added the following features:
Upgrade to Querydsl 4, Hibernate 5, OpenJPA 2.4, and EclipseLink 2.6.1.
However I still don't see the proper way to configure it.
According to this page, You can not use Open Jpa with spring 5.
But this is an example for spring 4.
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
#EnableJpaRepositories(basePackages = "com.baoviet.mhol.persistence.dao")
#ComponentScan("com.baoviet.mhol.service")
public class JpaConfig {
#Bean(destroyMethod ="" )
public DataSource dataSource(#Value("${db.jndi}") String jndiName) {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
lookup.setResourceRef(true);
return lookup.getDataSource(jndiName);
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.baoviet.mhol.persistence.model");
lef.setJpaDialect(new OpenJpaDialect());
return lef;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
OpenJpaVendorAdapter OpenJpaVendorAdaptor = new OpenJpaVendorAdapter();
OpenJpaVendorAdaptor.setShowSql(true);
OpenJpaVendorAdaptor.setGenerateDdl(true);
OpenJpaVendorAdaptor.setDatabasePlatform("org.OpenJpa.dialect.Oracle10gDialect");
return OpenJpaVendorAdaptor;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
}
Remember, in this case You do not need to persistence.xml file.
And This is Application.properties.
db.jndi=jdbc/batch
Note:
OpenJpa needs Persistence.xml to enhance entities at compile time.
So, You need to use different method for entity enhancement or provide your metadata in xml other than persistence.xml or use persistence.xml instead of data source.
You need to search for these more.
for entity enhancement solutions, please visit hear

Hibernate MultiTenancy with spring jpa

I want to add multiple tenant into my application using separate schema.My application is based on spring jpa and hibernate. I implement MultiTenantConnectionProvider and CurrentTenantIdentifierResolver.
And my configuration class is:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("com.**.api.entity");
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(hibernateJpaVendorAdapter);
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.globally_quoted_identifiers",true);
jpaProperties.put("hibernate.dialect",org.hibernate.dialect.MySQL5Dialect.class);
jpaProperties.put("hibernate.multi_tenant_connection_provider",multiTenantConnectionProvider);
jpaProperties.put("hibernate.tenant_identifier_resolver",currentTenantIdentifierResolver);
jpaProperties.put("hibernate.multiTenancy","SCHEMA");
entityManagerFactory.setJpaProperties(jpaProperties);
return entityManagerFactory;
}
And I use MapDataSourceLookup to save dataSources.It works.But it's a little problem. I must assign the packagesToScan.I want it to be a basic service.And some application depend on it.It seems that assign the packagesToScan is not a good practice.
Is there any better way to do it?

How to define HSQ DB properties in Spring JPA using annoations

I am running HSQL DB as a Im memory using run manger Swing.I have to connect the HSQLDB server from Spring JPA repository using annotations.
My repository class.
#RepositoryRestResource
public interface Vehicle extends JpaRepository<Vehicle , BigInteger>{
public List<Vehicle > findAll(Sort sort);
}
service Method:
#Service
public class LocationService {
#Autowired
VehicletRepository vehicleRepository = null;
/**
* This method is to get all the locations from the repository
*/
public List<Vehicle> getVehicless() {
Order order = new Order(Direction.ASC,"vehicleCode");
Sort sort = new Sort(order);
List<Airport> airports = vehicletRepository .findAll(sort);
System.out.println("inside service");
return vehicles;
}
}
Anyone help to achieve Spring JPA conenction with HSQL DB using annotations.
I assume you dont use Spring boot:
you need #Configuration class -(it basically is new way to configure spring applications in java ) with #EnableJpaRepositories which turn it spring data jpa/ spring data rest for you. You will also have to specify your entity manager, transaction manager and data source beans. Example below:
#Configuration
#EnableJpaRepositories("your.package.with.repositories")
public class DBConfig{
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
DBConfigurationCommon.configureDB(dataSource, your_jdbc_url_here, db_username_here, db_password_here);
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
//you may need to define new Properties(); here with hibernate dialect and add it to entity manager factory
entityManagerFactoryBean.setPackagesToScan("your_package_with_domain_classes_here");
return entityManagerFactoryBean;
}
}

AbstractRoutingDatasource and hibernate.dialect with multiples datasources

In my Spring Java Config file,i use AbstractRoutingDatasource successfully to switch multiple databases connections.
public MyRoutingDataSource myRoutingDataSource() {
MyRoutingDataSource dataSource = new MyRoutingDataSource();
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
dataSource.setDefaultTargetDataSource(defaultDataSource());
dataSource.setTargetDataSources(targetDataSources);
return dataSource;
}
But when i want specific SQL requests that differs from datasources PostgreSQL/Oracle etc.. (like pagination limit/rowNums), i have to associated a specific hibernate dialect.
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setShowSql(true);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL81Dialect");
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("fr.appli.model");
factory.setDataSource(myRoutingDataSource());
My question is how can i change hibernate dialect in my EntityManager, when i change datasource from with AbstractRoutingDatasource ? Is it possible to do it programmatically ?
Thanks
I think to achive this you will need multiple datasource configuration files and each database has its own SessionFactory object in an DAO which will permof DB operations.
For example :
SessionFactory sessionFactory1 = new Configuration().configure("oracleconfig.cfg.xml").buildSessionFactory();
SessionFactory sessionFactory2 = new Configuration().configure("mysqlconfig.cfg.xml").buildSessionFactory();

Resources