Relationship between two entities of different schemes - Spring Boot Data JPA - java

Is it possible to cross join between two different database tables (2 DataSources) in Spring Boot using JPA? If so, how would you configure this configuration? In the application.properties, 4 databases are already being defined and 4 files have been created that represent the configurations of the DataSources. The scenario is that there is a DataSource 1 table that has a FOREIGN KEY with a DataSource 2 table, but when the application is raised an Exception is generated:
#OneToOne or #ManyToOne on com.smart4.bdcentral.domain.files.IndividuoFoto .persons references an unknown entity: com.smart4.bdcentral.domain.main.IndividuoPessoa
DataSource 1
package com.smart4.configBases;
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import com.google.common.base.Preconditions;
#Configuration
#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(basePackages = {"com.smart4.bdcentral.repository.main"},
entityManagerFactoryRef = "bdCentralMainEntityManager",
transactionManagerRef = "bdCentralMainTransactionManager")
public class BdCentralMain {
#Autowired
private Environment env;
public BdCentralMain() {
super();
}
#Bean
public LocalContainerEntityManagerFactoryBean bdCentralMainEntityManager() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(bdCentralMainDataSource());
em.setPackagesToScan(new String[] { "com.smart4.bdcentral.domain.main" });
em.setPersistenceUnitName("bdcentralmain");
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
em.setJpaVendorAdapter(vendorAdapter);
final HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("bdcentralmain.hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("bdcentralmain.hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource bdCentralMainDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.pass")));
return dataSource;
}
#Bean
public PlatformTransactionManager bdCentralMainTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(bdCentralMainEntityManager().getObject());
return transactionManager;
}
}
DataSource 2
package com.smart4.configBases;
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import com.google.common.base.Preconditions;
#Configuration
#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(basePackages = {"com.smart4.bdcentral.repository.files"},
entityManagerFactoryRef = "bdCentralFilesEntityManager",
transactionManagerRef = "bdCentralFilesTransactionManager")
public class BdCentralFiles {
#Autowired
private Environment env;
public BdCentralFiles() {
super();
}
#Bean
public LocalContainerEntityManagerFactoryBean bdCentralFilesEntityManager() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(bdCentralFilesDataSource());
em.setPackagesToScan(new String[] { "com.smart4.bdcentral.domain.files" });
em.setPersistenceUnitName("bdcentralfiles");
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
em.setJpaVendorAdapter(vendorAdapter);
final HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("bdcentralfiles.hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("bdcentralfiles.hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource bdCentralFilesDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.pass")));
return dataSource;
}
#Bean
public PlatformTransactionManager bdCentralFilesTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(bdCentralFilesEntityManager().getObject());
return transactionManager;
}
}

not much to say with just the datasources, check the annotation configuration and make sure your objects are #Entity annotated. It doesn't sound like you actually want a "cross join", also you're looking at Hibernate, I kept reading Spring Boot JPA as spring "Data" JPA and was getting confused as to why it wasn't data jpa lol.

Related

Bean overriding although there is no overrided bean

I am implementing a read-only db source but although there is no conflicting bean, it got bean error.
How can I fix the below issue ?
The bean 'routingDataSource', defined in class path resource [io/api/masterSlave/datasources/DataSourcesConfiguration.class], could not be registered. A bean with that name has already been defined in file [/Users/neslihan.bozer/Codes/api-backend/target/classes/io/api/masterSlave/routing/RoutingDataSource.class] and overriding is disabled.
package io.api.masterSlave.datasources;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import io.api.masterSlave.properties.Properties;
import io.api.masterSlave.routing.RoutingDataSource;
#Configuration
#ComponentScan
#EnableJpaRepositories("io.api.persistence.repository")
public class DataSourcesConfiguration {
#Autowired
private Properties props;
#Bean(name = "masterDataSource1")
#Primary
public DataSource masterDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(props.getProperty("spring.datasource.master.driver-class-name"));
dataSource.setDefaultAutoCommit(false);
dataSource.setUsername(props.getProperty("spring.datasource.master.username"));
dataSource.setPassword(props.getProperty("spring.datasource.master.password"));
dataSource.setUrl(props.getProperty("spring.datasource.master.url"));
return dataSource;
}
#Bean
public RoutingDataSource routingDataSource() {
RoutingDataSource dataSource = new RoutingDataSource();
dataSource.setDefaultTargetDataSource(masterDataSource());
Map<Object, Object> targets = new HashMap<>();
targets.put(DataSourceType.MASTER, masterDataSource());
targets.put(DataSourceType.SLAVE, slaveDataSource());
dataSource.setTargetDataSources(targets);
dataSource.afterPropertiesSet();
return dataSource;
}
#Bean(name = "slaveDataSource2")
public DataSource slaveDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(props.getProperty("spring.datasource.slave.driver-class-name"));
dataSource.setDefaultAutoCommit(false);
dataSource.setUsername(props.getProperty("spring.datasource.slave.username"));
dataSource.setPassword(props.getProperty("spring.datasource.slave.password"));
dataSource.setUrl(props.getProperty("spring.datasource.slave.url"));
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(masterDataSource());
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.parseBoolean(props.getProperty("spring.jpa.generate-ddl")));
Map<String, String> additionalProperties = new HashMap<>();
additionalProperties.put("hibernate.dialect", props.getProperty("spring.jpa.dialect"));
LocalContainerEntityManagerFactoryBean factory = builder.dataSource(routingDataSource())
.packages("io.api.persistence.entity").persistenceUnit("routingEntityMF").properties(additionalProperties)
.build();
factory.setJpaVendorAdapter(vendorAdapter);
factory.afterPropertiesSet();
return factory;
}
}
RoutingDataSource.java
package io.api.masterSlave.routing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Service;
#Service
public class RoutingDataSource extends AbstractRoutingDataSource {
#Autowired
private DbHolder dbHolder;
#Override
protected Object determineCurrentLookupKey() {
return dbHolder.getDbType();
}
}

EntityManager doesn't translate camel case to snake case

I'm using SpringBoot 2.7.0 and trying to set an entity manager cause I have 2 databases.
But the entityManager that I instantiated doesn't work like default one.
It doesn't translate camel case to snake case for the properties of entity when it creates tables.
Even it doesn't follow the settings in application.yml. for example, spring.jpa.show-sql.
I configured it with below code.
#Slf4j
#RequiredArgsConstructor
#EnableJpaAuditing
#EnableJpaRepositories(basePackages = "com.xxx.yyy", entityManagerFactoryRef = "businessEntityManagerFactory", transactionManagerRef = "businessTransactionManager")
#EntityScan(basePackages = "com.xxx.yyy")
#Configuration
public class JpaConfiguration {
#Bean
public LocalContainerEntityManagerFactoryBean businessEntityManagerFactory(EntityManagerFactoryBuilder builder,
DataSource businessDataSource) {
return builder
.dataSource(businessDataSource)
.packages("com.xxx.yyy")
.build();
}
#Bean
public PlatformTransactionManager businessTransactionManager(LocalContainerEntityManagerFactoryBean businessEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(businessEntityManagerFactory.getObject()));
}
}
Does anyone know how I can instantiate an entity manager with same settings like spring boot default one?
Spring's convention-over-configuration does not work well with multiple database configurations.
Particuallary the configuration has to be autowired "manually". That's the reason springt.jpa.show-sql is not considered.
I will post an example on how to configure a database "manually".
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
#EnableTransactionManagement
#EnableAutoConfiguration(exclude = {JdbcRepositoriesAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class, DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
#EnableJpaRepositories(basePackageClasses = {ExampleXyzRepository.class}, transactionManagerRef = DatabaseConfig.SPRING_TRANSACTION_MANAGER)
public class DatabaseConfig {
public static final String SPRING_TRANSACTION_MANAGER = "springTransactionManager";
private static LocalContainerEntityManagerFactoryBean createEntityManagerFactory(
final ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider, final JpaProperties jpaProperties,
final HibernateProperties hibernateProperties, final DataSource dataSource, final Class<?> exampleEntityClass, final String persistenceUnit) {
return createEntityManagerFactoryBuilder(persistenceUnitManagerProvider.getIfAvailable(), jpaProperties, hibernateProperties)
.dataSource(dataSource)
.packages(exampleEntityClass)
.persistenceUnit(persistenceUnit)
.build();
}
private static EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(
final PersistenceUnitManager persistenceUnitManager, final JpaProperties jpaProperties, final HibernateProperties hibernateProperties) {
final JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
final Map<String, Object> expandedProperties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
return new EntityManagerFactoryBuilder(jpaVendorAdapter, expandedProperties, persistenceUnitManager);
}
private static JpaVendorAdapter createJpaVendorAdapter(final JpaProperties jpaProperties) {
final AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
if (jpaProperties.getDatabase() != null) {
adapter.setDatabase(jpaProperties.getDatabase());
}
return adapter;
}
private static HikariDataSource initializeDataSource(final DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
#ConfigurationProperties("spring.datasource")
public DataSourceProperties springDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.datasource.hikari")
public DataSource springDataSource(#Qualifier("springDataSourceProperties") final DataSourceProperties springDataSourceProperties) {
return initializeDataSource(springDataSourceProperties);
}
#Bean
#ConfigurationProperties("spring.jpa")
public JpaProperties springJpaProperties() {
return new JpaProperties();
}
#Bean
#ConfigurationProperties("spring.jpa.hibernate")
public HibernateProperties springHibernateProperties() {
return new HibernateProperties();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
final ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider,
#Qualifier("springJpaProperties") final JpaProperties springJpaProperties,
#Qualifier("springHibernateProperties") final HibernateProperties springHibernateProperties,
#Qualifier("springDataSource") final DataSource springDataSource) {
return createEntityManagerFactory(persistenceUnitManagerProvider, springJpaProperties, springHibernateProperties, springDataSource, ExampleXyzEntity.class, "default-persistence-unit");
}
#Bean(SPRING_TRANSACTION_MANAGER)
public JpaTransactionManager transactionManager(#Qualifier("entityManagerFactory") final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
See how the configuration of DataSourceProperties, HibernateProperties, DataSource and JpaProperties are bound.
The second database is configured similar.
But:
use a different configuration prefix and not spring.jpa and spring.datasource - obviously
define the transactionManager in the org.springframework.transaction.annotation.Transactional while accessing the second database, e.g. in the CrudRepository
Sven's answer might be right but I didn't try it because I saw this after I found the solution and it looked requiring many changes my codes.
I figured this out with below codes
#Bean
public LocalContainerEntityManagerFactoryBean businessEntityManagerFactory(DataSource businessDataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(businessDataSource);
emf.setPackagesToScan("com.xxx.yyy");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(Boolean.valueOf(env.getProperty("spring.jpa.show-sql")));
emf.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.format_sql", env.getProperty("spring.jpa.properties.hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.properties.hibernate.hbm2ddl.auto"));
properties.put("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy");
properties.put("hibernate.implicit_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
emf.setJpaPropertyMap(properties);
return emf;
}

Table is not being created, despite `hibernate.hbm2ddl.auto=update` in application.properties

For some reason, my db tables are not being created according to the entity model in the codebase. I am looking for the codebase to lead, and create the tables in the db, every time the server starts.
I have this in src/main/resources/application.properties
################### DataSource Configuration ##########################
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:~/test
jdbc.username=sa
jdbc.password=
################### spring config ####################################
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
################### Hibernate Configuration ##########################
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
I bet some of that is redundant or maybe even contradictory. I doubt I need spring.jpa and hibernate, since they conflict. My current preference is to use Hibernate for ORM.
I also have:
package huru.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Trivial JPA entity for vertx-spring demo
*/
#Entity
#Table(name="HURU_USER")
public class User {
#Id
#Column(name="ID")
private Integer productId;
#Column
private String description;
public Integer getProductId() {
return this.productId;
}
public String getDescription() {
return this.description;
}
}
and I have this:
package huru.repository;
import huru.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* Spring Data JPA repository to connect our service bean to data
*/
public interface UserRepository extends JpaRepository<User, Integer> {
}
and here is the SpringConfiguration
package huru.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.Properties;
/**
* Simple Java Spring configuration to be used for the Spring example application. This configuration is mainly
* composed of a database configuration and initial population via the script "products.sql" of the database for
* querying by our Spring service bean.
* <p>
* The Spring service bean and repository are scanned for via #EnableJpaRepositories and #ComponentScan annotations
*/
#Configuration
#EnableJpaRepositories(basePackages = {"huru.repository"})
#PropertySource(value = {"classpath:application.properties"})
#ComponentScan("huru.service")
public class SpringConfiguration {
#Autowired
private Environment env;
#Bean
#Autowired
public DataSource dataSource(DatabasePopulator populator) {
final DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(env.getProperty("jdbc.driverClassName"));
ds.setUrl(env.getProperty("jdbc.url"));
ds.setUsername(env.getProperty("jdbc.username"));
ds.setPassword(env.getProperty("jdbc.password"));
DatabasePopulatorUtils.execute(populator, ds);
return ds;
}
#Bean
#Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(final DataSource dataSource) {
final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.TRUE);
vendorAdapter.setShowSql(Boolean.TRUE);
factory.setDataSource(dataSource);
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("huru.entity");
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
factory.setJpaProperties(jpaProperties);
return factory;
}
#Bean
#Autowired
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory.getObject());
}
#Bean
public DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(false);
populator.addScript(new ClassPathResource("users.sql"));
return populator;
}
}
package huru.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.Properties;
/**
* Simple Java Spring configuration to be used for the Spring example application. This configuration is mainly
* composed of a database configuration and initial population via the script "products.sql" of the database for
* querying by our Spring service bean.
* <p>
* The Spring service bean and repository are scanned for via #EnableJpaRepositories and #ComponentScan annotations
*/
#Configuration
#EnableJpaRepositories(basePackages = {"huru.repository"})
#PropertySource(value = {"classpath:application.properties"})
#ComponentScan("huru.service")
public class SpringConfiguration {
#Autowired
private Environment env;
#Bean
#Autowired
public DataSource dataSource(DatabasePopulator populator) {
final DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(env.getProperty("jdbc.driverClassName"));
ds.setUrl(env.getProperty("jdbc.url"));
ds.setUsername(env.getProperty("jdbc.username"));
ds.setPassword(env.getProperty("jdbc.password"));
DatabasePopulatorUtils.execute(populator, ds);
return ds;
}
#Bean
#Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(final DataSource dataSource) {
final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.TRUE);
vendorAdapter.setShowSql(Boolean.TRUE);
factory.setDataSource(dataSource);
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("huru.entity");
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
factory.setJpaProperties(jpaProperties);
return factory;
}
#Bean
#Autowired
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory.getObject());
}
#Bean
public DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(false);
populator.addScript(new ClassPathResource("users.sql"));
return populator;
}
}
so yeah like I said, I am hoping to see a table called "USER" in the db, but it doesn't seem to be happening.
Yeah the datasource info in application.properties was wrong, should have looked like this instead:
jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/oleg
jdbc.username=postgres
jdbc.password=postgres

how do i resolve getCurrentSession() in mycode

i am beginner in java,spring&hibernate. when i using sessionFactory.getCurrentSession().saveOrUpdate(employee); igot error. but when i use sessionFactory.openSession().saveOrUpdate(employee); database insertion is possible. i want to use getCurrentSession() instead of open session .
mycode
myservice is
package com.simplecrud.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.simplecrud.dao.EmployeeDao;
import com.simplecrud.model.Employee;
#Service("employeeService")
#Transactional
public class EmployeeService {
#Autowired
EmployeeDao dao;
#Transactional
public String create(Employee employee)
{
System.out.println("service"+employee);
dao.create(employee);
return null;
}
}
my dao is
package com.simplecrud.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import com.simplecrud.model.Employee;
#Component
#Repository
public class EmployeeDao {
#Autowired
SessionFactory sessionFactory;
public void create(Employee employee){
sessionFactory.openSession().saveOrUpdate(employee);
/*sessionFactory.getCurrentSession().saveOrUpdate(employee);*/
/* protected Session getSession(){
return sessionFactory.getCurrentSession();
}*/
}
}
config file
package com.simplecrud.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration //Marks this class as configuration
//Specifies which package to scan
#ComponentScan("com.simplecrud")
//Enables Spring's annotations
#EnableWebMvc
public class Config {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/employee_db");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("mysql");
return driverManagerDataSource;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
// properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.c3p0.minPoolSize", "5");
properties.put("hibernate.c3p0.maxPoolSize", "10");
properties.put("hibernate.c3p0.idleTestPeriod", "300");
properties.put("hibernate.c3p0.timeout", "600");
properties.put("hibernate.c3p0.max_statement", "50");
properties.put("hibernate.c3p0.testConnectionOnCheckout", "false");
properties.setProperty("timeZone", "serverTimezone");
properties.put("hibernate.c3p0.preferredTestQuery", "select 1");
return properties;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addProperties(getHibernateProperties());
sessionBuilder.scanPackages("com.simplecrud.model");
//sessionBuilder.setInterceptor(new MySQLCalcFoundRowsInterceptor());
return sessionBuilder.buildSessionFactory();
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
}
help me anyone..

Adding a second datasource - SpringBoot RepositoryRestService PersistenceConfig

I'm trying to find the best approach to adding a second datasource to our application. The main purpose is to expose CRUD ops against the db via rest, & need to bounce against a 2nd db for authentication and role management. We are not using XML configs.
Is there a way to simply add a second datasource bean in the existing PersistenceConfig.java file, or do we need to replicate the whole config class for the second db instance?
The application:
package foo;
import foo.config.PersistenceConfig;
import foo.config.RepositoryRestConfig;
import foo.config.WebConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#ComponentScan
#EnableJpaRepositories
#Import({PersistenceConfig.class, WebConfig.class, RepositoryRestConfig.class})
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The Repo:
package foo.repository;
import foo.Widget;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.List;
#RepositoryRestResource(collectionResourceRel = "widgets", path = "widgets")
public interface WidgetsRepository extends CrudRepository<Widget, Long> {
List<Widget> findByWidgetId(#Param("widgetid") long widgetId);
}
The persistence config :
package foo.config;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.orm.jpa.JpaDialect;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
#Configuration
#Import(RepositoryRestMvcConfiguration.class)
#EnableJpaRepositories
#EnableTransactionManagement
public class PersistenceConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.SQL_SERVER);
vendorAdapter.setShowSql(true);
final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("foo.model");
factory.setDataSource(dataSource());
return factory;
}
#Bean(destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setUrl("jdbc:sqlserver://127.0.0.1:1433;databaseName=fooDB");
dataSource.setUsername("sa");
dataSource.setPassword("*******");
dataSource.setTestOnBorrow(true);
dataSource.setTestOnReturn(true);
dataSource.setTestWhileIdle(true);
dataSource.setTimeBetweenEvictionRunsMillis(1800000L);
dataSource.setNumTestsPerEvictionRun(3);
dataSource.setMinEvictableIdleTimeMillis(1800000L);
dataSource.setValidationQuery("SELECT 1");
return dataSource;
}
#Bean
public JpaDialect jpaDialect() {
return new HibernateJpaDialect();
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
}
Thank you for your assistance...
Take a look at #Qualifier annotation. With this annotation you are able to define various beans of the same type and assign them names. It is equivalent of id parameter in bean XML tag.
This is relevant part of Spring documentation.
First of all, it's worth noting that almost all of the configuration in PersistenceConfig is redundant as Spring Boot will automatically configure it for you. Pretty much the only thing that is non-default and you need to specify is your DataSource configuration, for example the SQLServer URL.
There's a section in the documentation that describes how to configure two DataSources using #Primary and application.properties:
Creating more than one data source works the same as creating the first one. You might want to mark one of them as #Primary if you are using the default auto-configuration for JDBC or JPA (then that one will be picked up by any #Autowired injections)."
#Bean
#Primary
#ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
You'd then configure these two DataSources using application.properties and the datasource.primary and datasource.secondary prefixes:
For example:
datasource.primary.jdbcUrl=jdbc:sqlserver://127.0.0.1:1433;databaseName=fooDB
datasource.primary.user=sa
datasource.primary.password=secret
datasource.primary.jdbcUrl=jdbc:sqlserver://127.0.0.1:1433;databaseName=barDB
datasource.primary.user=sa
datasource.primary.password=secret

Categories

Resources