Spring boot with apache OpenJPA - spring

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

Related

spring boot with multiple databases

I'm trying to write an application that accesses data from two sources. I'm using Spring Boot 2.3.2. I've looked at several sources for info about how to configure the app: the Spring documentation talks about setting up multiple datasources, but does not explain how to link up JPA repositories. This Baeldung article goes a lot further, but I'm looking to take advantage of autoconfiguration in Spring.
So far, I've created a separate package, added a config class (along with model and repositories), and included this package in scanBasePackages so that it's picked up. Since I'll have more than one datasource, I've added this to my #SpringBootApplication:
#Bean
#Primary
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
This successfully loads up my Spring app using the standard spring config values. The two databases are on different servers, but should share characteristics (other than url and credentials).
So, my auxiliary configuration file looks like this
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "orgEntityManagerFactory",
transactionManagerRef = "orgTransactionManager",
basePackages = {
"pacage2.repositories"
}
)
public class DataSourceConfiguration {
// added because of this answer: https://stackoverflow.com/a/51305724/167889
#Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), new HashMap<>(), null);
}
#Bean
#ConfigurationProperties(prefix = "external.datasource")
public DataSourceProperties orgDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
public HikariDataSource orgDataSource(#Qualifier("orgDataSourceProperties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean orgEntityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("orgDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("package2.model")
.build();
}
#Bean
public PlatformTransactionManager orgTransactionManager(
#Qualifier("orgEntityManagerFactory") EntityManagerFactory entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Now, the error I'm getting right now is Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set. However, I have that value in my config and it's applied by the Spring auto config. I believe it needs to be set in the EntityManagerFactoryBuilder and by creating my own, the autoconfig isn't getting applied.
How can I have my cake and eat it too? I'd like to leverage as much of the robust autoconfiguration that Spring provides to setup datasources and wire them to the appropriate repositories. Effectively, all that I want to change is the url and credentials, and I can separate the entities and repositories into a completely separate package for easy scanning.

Will spring Boot datasource properties work if we configure datasource programmatically in Spring Boot

Will Spring Boot datasource properties work if we configure datasource programmatically?
The following properties worked only when I fetch DB configuration from application.properties. If I configure datasource programmatically the following properties are not working.
spring.datasource.tomcat.initial-size=10
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=5
I used the following code to configure datasource programmatically
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
#Primary
public DataSource dataSource() {
return DataSourceBuilder.create().username(userName).password(password).url(url).driverClassName(driverName)
.build();
}
To make it work programmatically I used the following code snippet.But I'm not convinced. I feel it is not a cleaner solution. I have to read at least 20 properties from application.properties and add it to PoolProperties.
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
#Primary
public DataSource dataSource() {
PoolProperties poolProperties = new PoolProperties();
poolProperties.setUrl(url);
poolProperties.setDriverClassName(driverName);
poolProperties.setUsername(userName);
poolProperties.setPassword(password);
poolProperties.setTestWhileIdle(false);
poolProperties.setTestOnBorrow(true);
poolProperties.setValidationQuery("SELECT 1 FROM DUAL");
poolProperties.setTestOnReturn(false);
poolProperties.setValidationInterval(30000);
poolProperties.setTimeBetweenEvictionRunsMillis(30000);
poolProperties.setInitialSize(10);
poolProperties.setMaxActive(10);
poolProperties.setMaxIdle(5);
poolProperties.setMinIdle(5);
poolProperties.setMaxWait(10000);
poolProperties.setRemoveAbandonedTimeout(60);
poolProperties.setMinEvictableIdleTimeMillis(30000);
poolProperties.setLogAbandoned(true);
poolProperties.setRemoveAbandoned(true);
DataSource datasource = new DataSource(); // import org.apache.tomcat.jdbc.pool.DataSource;
datasource.setPoolProperties(poolProperties);
return datasource;
}
It there way we can make the following default Spring Boot properties work?
spring.datasource.tomcat.initial-size=10
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=5
remember to give tomcat from properties for db in property files like this.
# Oracle DB - "foo"
spring.datasource.tomcat.url=jdbc:oracle:thin:#//db-server-foo:1521/FOO
spring.datasource.tomcat.username=fooadmin
spring.datasource.tomcat.password=foo123
spring.datasource.tomcat.initial-size=10
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=5
then configure datasource like this.
/**
* Auto-configured DataSource
*/
#ConfigurationProperties(prefix = "spring.datasource.tomcat")
#Bean
#Primary
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}

transaction working without #EnableTransactionManagement

I am using spring boot with mybatis. I am not using spring data or anything but on my service if i use annotation like
#Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor= {Exception.class})
it is handling transaction.I have not specified anywhere to enable transaction management. How spring boot enable this. How is this possible ?
By default Spring Boot does initiate the transaction autoconfigration if database source properties does exist.
See the DataSourceTransactionManagerAutoConfiguration code.
#Configuration
#ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
#AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
#EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration
// other code
#Bean
#ConditionalOnMissingBean(PlatformTransactionManager.class)
public DataSourceTransactionManager transactionManager(
DataSourceProperties properties) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}
The datasource properties are: url, driverClassName, jndiName etc.

Integrating Hibernate OGM and Spring Data JPA

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.

How do you autowire/inject your datasource in Spring-boot?

I have been working with Spring boot for a bit now, and the datasource is always configured in your application.properties in every example I have seen, kind of like this:
# DataSource configuration
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/abcdef
spring.datasource.username=******
spring.datasource.password=******
However, lately I have been trying to integrate Spring Social, and the examples I have seen configure it in java in a config file like this:
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("db.driver"));
dataSource.setUrl(env.getProperty("db.url"));
dataSource.setUsername(env.getProperty("db.username"));
dataSource.setPassword(env.getProperty("db.password"));
return dataSource;
}
This allows for the datasource object to later be injected or autowired into the social config as seen here for example.
My question is, do I need to configure a datasource bean like this to be able to later inject the datasource, or will Spring-boot handle that for me?
Not a Spring (or Boot) expert by any means, but Spring Boot will auto-provide a Bean of type DataSource if the properties are there and there's a requirement for it. To use it you just #Autowire it.
Try this . If there are multiple #Configuration in springboot , You can import the the other config(DataSourceConfig) into your main AppConfig.
And then Using #PropertySource pull in the db url,username,password etc
https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s03.html
#Configuration
#Import(DataSourceConfig.class)
#PropertySource("classpath:application.properties")
public class SpringbatchConfig {
#Autowired
DataSourceConfig dataSourceConfig;
#Bean
public void myService myService() {
return new myServiceImpl(dataSourceConfig.dataSource());
}
}

Resources