I use Spring Data JPA and use multiple database, so I must configure it myself instead of using #HibernateJpaAutoConfiguration.
public class TesterDbConfig {
#Autowired(required = false)
private PersistenceUnitManager persistenceUnitManager;
#Bean
public JpaProperties testerJpaProperties() {
JpaProperties jpaProperties = new JpaProperties();
return jpaProperties;
}
#Bean
#Primary
#ConfigurationProperties(prefix = "datasource.primary")
public DataSource testerDataSource() {
return (DataSource) DataSourceBuilder.create().type(DataSource.class).build();
}
#Bean
public LocalContainerEntityManagerFactoryBean testerEntityManager(
JpaProperties testerJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(testerJpaProperties);
return builder.dataSource(testerDataSource()).packages(Cabang.class).persistenceUnit("primary")
.build();
}
#Bean
public JpaTransactionManager testerTransactionManager(EntityManagerFactory testerEntityManager) {
return new JpaTransactionManager(testerEntityManager);
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(
JpaProperties testerJpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(testerJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, testerJpaProperties,
this.persistenceUnitManager);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties testerJpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(testerJpaProperties.isShowSql());
adapter.setDatabase(testerJpaProperties.getDatabase());
adapter.setDatabasePlatform(testerJpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(testerJpaProperties.isGenerateDdl());
return adapter;
}
}
With this, every time I create a model, I must use #Column in every variable because in my database, I use snake case, but in model class, I use camel case.
How can I set the Hibernate naming strategy?
You can set it via JpaProperties, which you already use in your configuration:
#Bean
public JpaProperties testerJpaProperties() {
JpaProperties jpaProperties = new JpaProperties();
JpaProperties.Hibernate hibernate = new JpaProperties.Hibernate();
hibernate.setNamingStrategy(SpringNamingStrategy.class);
jpaProperties.setHibernate(hibernate);
return jpaProperties;
}
And add
#Bean
public LocalContainerEntityManagerFactoryBean testerEntityManager(
JpaProperties testerJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(testerJpaProperties);
return builder.dataSource(testerDataSource())
.packages(Cabang.class)
.persistenceUnit("primary")
.properties(Collections.singletonMap("hibernate.ejb.naming_strategy",testerJpaProperties.getHibernate().getNamingStrategy()))
.build();
}
Related
Im new to spring framework and I Want to migrate data from One DB to another using Spring boot n Batch
Im trying to read from an Mysql db with an item reader and write it to an Oracle db using an item writer of the same job.
Im able to read the data from the Mysql db but unable to write it to Oracle Db as the writer is trying it write it in Mysql Db itself.
Im not sure why the connection is not switching to Oracle db.
Please help me over here what im doing wrong.
Application properties
server.port=8082
spring.batch.job.enabled= false
spring.datasource.url = jdbc:mysql://localhost:3306/projectdb1
spring.datasource.username = root
spring.datasource.password = Mech_2015
spring.datasource.driverClassName = com.mysql.jdbc.Driver
#second db2 ...
db2.datasource.url = jdbc:oracle:thin:#localhost:1521:xe
db2.datasource.username = system
db2.datasource.password = Mech_2015
db2.datasource.driverClassName = oracle.jdbc.driver.OracleDriver
Entity Managers
package com.techprimers.springbatchexample1.entity.manger;
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "radiusEntityManager", transactionManagerRef = "radiusTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userrepo")
public class RadiusConfig {
private final PersistenceUnitManager persistenceUnitManager;
public RadiusConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
}
#Bean
#ConfigurationProperties("spring.jpa")
public JpaProperties radiusJpaProperties() {
return new JpaProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties radiusDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix = "spring.datasource.properties")
public DataSource radiusDataSource() {
return (DataSource) radiusDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
}
#Bean(name = "radiusEntityManager")
public LocalContainerEntityManagerFactoryBean radiusEntityManager(JpaProperties radiusJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(radiusJpaProperties);
return builder.dataSource(radiusDataSource()).packages(User.class).persistenceUnit("userDs").build();
}
#Bean
public JpaTransactionManager radiusTransactionManager(EntityManagerFactory radiusEntityManager) {
return new JpaTransactionManager(radiusEntityManager);
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties radiusJpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(radiusJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, radiusJpaProperties.getProperties(),
this.persistenceUnitManager);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabase(jpaProperties.getDatabase());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
return adapter;
}
}
package com.techprimers.springbatchexample1.entity.manger;
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "esbEntityManager", transactionManagerRef = "esbDetailsTransactionManager", basePackages = "com.techprimers.springbatchexample1.repository.userdetails")
public class EsbConfig {
private final PersistenceUnitManager persistenceUnitManager;
public EsbConfig(ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
this.persistenceUnitManager = persistenceUnitManager.getIfAvailable();
}
#Bean
#ConfigurationProperties("db2.jpa")
public JpaProperties esbJpaProperties() {
return new JpaProperties();
}
#Bean
#ConfigurationProperties("db2.datasource")
public DataSourceProperties esbDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix = "db2.datasource.properties")
public DataSource esbDataSource() {
return (DataSource) esbDataSourceProperties().initializeDataSourceBuilder().type(DataSource.class).build();
}
#Bean(name = "esbEntityManager")
public LocalContainerEntityManagerFactoryBean esbEntityManager(JpaProperties esbJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(esbJpaProperties);
return builder.dataSource(esbDataSource()).packages(UserDetails.class).persistenceUnit("userDetailDs").build();
}
#Bean
public JpaTransactionManager esbTransactionManager(EntityManagerFactory esbEntityManager) {
return new JpaTransactionManager(esbEntityManager);
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties esbJpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(esbJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter, esbJpaProperties.getProperties(),
this.persistenceUnitManager);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabase(jpaProperties.getDatabase());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
return adapter;
}
}
Batch Config
package com.techprimers.springbatchexample1.config;
#Configuration
#EnableBatchProcessing
public class SpringBatchConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchConfig.class);
#Bean
#Primary
#Qualifier("radiusDatasource")
#ConfigurationProperties(prefix = "spring.datasource")
DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix = "db2.datasource")
#Qualifier("esbDatasource")
DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public InspectionProcessor processor() {
return new InspectionProcessor();
}
#Bean
public JdbcCursorItemReader<User> reader() {
JdbcCursorItemReader<User> cursorItemReader = new JdbcCursorItemReader<>();
cursorItemReader.setDataSource(mysqlDataSource());
cursorItemReader.setSql("SELECT ID,CNAME,SID,CREATEDDATE,COMPLETEDDATE FROM INSPECTION");
cursorItemReader.setRowMapper(new InspectionDetailRowmapper());
return cursorItemReader;
}
private static final String QUERY_INSERT_STUDENT = "INSERT "
+ "INTO inspect(id,cname,completeddate,createddate,lastupdateddate,sid) " + "VALUES (?,?,?,?,?,?)";
#Bean
ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate) {
LOGGER.info("Starting writer");
JdbcBatchItemWriter<UserDetails> databaseItemWriter = new JdbcBatchItemWriter<>();
databaseItemWriter.setDataSource(oracleDataSource());
databaseItemWriter.setJdbcTemplate(jdbcTemplate);
LOGGER.info(" writer");
databaseItemWriter.setSql(QUERY_INSERT_STUDENT)
ItemPreparedStatementSetter<UserDetails> valueSetter = new UserDetailsPreparedStatementSetter();
databaseItemWriter.setItemPreparedStatementSetter(valueSetter);
return databaseItemWriter;
}
#Bean
Step dataMigrationStep(ItemReader<User> reader, ItemProcessor<User, UserDetails> processor,
ItemWriter<UserDetails> databsaeItemWriter, StepBuilderFactory stepBuilderFactory) {
return stepBuilderFactory.get("dataMigrationStep").<User, UserDetails>chunk(5).reader(reader)
.processor(processor).writer(databsaeItemWriter).build();
}
#Bean
Job dataMigrationJob(JobBuilderFactory jobBuilderFactory, #Qualifier("dataMigrationStep") Step dataMigrationStep) {
return jobBuilderFactory.get("csvFileToDatabaseJob").incrementer(new RunIdIncrementer()).flow(dataMigrationStep)
.end().build();
}
}
Your writer does not inject properly the database where to write your data
this
#Bean
ItemWriter<UserDetails> databaseItemWriter(DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate)
instead of
#Bean
ItemWriter<UserDetails> databaseItemWriter(#Qualifier("esbDatasource") DataSource dataSource, NamedParameterJdbcTemplate jdbcTemplate)
I am using spring data jpa. I am using two data sources so I have configured my own data sources and they are working. But When I am using two data sources, spring boot automatically is creating foriegn keys to my table. But when I have disabled the manual configuration & using the default data source, then it is not happening? How do I change my code.
Here are my config class
Primary
#Configuration
#EnableJpaRepositories(basePackages="com.example.repository",
entityManagerFactoryRef = "primaryEntityManagerFactory")
public class DataSourceConfiguration {
#Bean(name="primaryDataSource")
#Primary
#ConfigurationProperties(prefix = "datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#Primary
public JpaTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(primaryEntityManagerFactory().getObject());
return tm;
}
#Bean(name="primaryEntityManagerFactory")
#Primary
LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(primaryDataSource());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());
return factoryBean;
}
}
Secondary
#Configuration
#EnableJpaRepositories(basePackages="com.example.repository1",
entityManagerFactoryRef = "secondaryEntityManagerFactory")
public class DS2Configuration {
#Bean(name="secondaryDataSource")
#ConfigurationProperties(prefix = "datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(secondaryEntityManagerFactory().getObject());
return tm;
}
#Bean(name="secondaryEntityManagerFactory")
LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(secondaryDataSource());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());
return factoryBean;
}
}
How do I change these so as to disable automatic foriegn key creation?
I have been trying to configure openjpa-slice with spring boot. The configuration is shared as follows:
#Configuration
public class DatasourceConfiguration extends JpaBaseConfiguration{
#Bean(name = "slice1")
public DataSource dataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("java:/MysqlXADS");
return dataSource;
}
#Bean(name = "slice2")
public DataSource dataSource2() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("java:/MysqlXADS2");
return dataSource;
}
#Override
protected Map<String, Object> getVendorProperties() {
HashMap<String, Object> map = new HashMap<String, Object>();
return map;
}
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("openjpa.BrokerFactory", "slice");
properties.put("openjpa.slice.Names", "One, Two");
properties.put("openjpa.slice.Master", "Two");
properties.put("openjpa.slice.Lenient", "false");
properties.put("openjpa.slice.ConnectionDriverName", "com.mysql.jdbc.Driver");
properties.put("openjpa.slice.One.ConnectionFactoryName", "java:/MysqlXADS");
properties.put("openjpa.slice.Two.ConnectionFactoryName", "java:/MysqlXADS2");
properties.put("openjpa.slice.DistributionPolicy", "com.services.sample.configuration.UserDistributionPolicy");
properties.put("openjpa.slice.TransactionPolicy" , "xa");
properties.put("openjpa.TransactionMode" , "managed");
properties.put("openjpa.ConnectionFactoryMode", "managed");
properties.put("openjpa.jdbc.DBDictionary", "mysql");
properties.put("openjpa.Log","DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE");
return builder
.dataSource(dataSource()).jta(true)
.properties(properties)
.packages("com.services.sample.domain.entity")
.persistenceUnit("sample")
.build();
}
#Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
OpenJpaVendorAdapter jpaVendorAdapter = new OpenJpaVendorAdapter();
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
}
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactory")EntityManagerFactory entityManagerFactory){
JtaTransactionManager transactionManager = new JtaTransactionManager();
return transactionManager;
}
}
persistence.xml
<persistence-unit name="sample" transaction-type="JTA" >
<description>generated-persistence-unit</description>
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class> ... </class>
</persistence-unit>
I have configured this with wildfly server 10. Both the xa-datasources point to different databases. However, when the application boots and I execute a query it just fetches the data from the datasource passed into the builder twice. Seems I have something wrong with the slice configuration. Not sure whats the problem in this case.
I have a simple Spring Boot application with the following auto-configuration properties:
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/mywebapp
spring.datasource.username=username
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=validate
These work fine and I'm able to setup Spring Data JpaRepositories:
public interface UserRepository extends JpaRepository<User, String>
{
User findByName(String name);
}
...for the following entities:
#Entity
public class User
{
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
protected String uuid;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String email;
}
...and use them like this:
#Transactional
public void updatePassword(String username, String password)
{
User user = userRepository.findByName(username);
user.setEmail("test#example.com"); // This gets persisted automatically by the JpaRepository.
}
Now I'm struggling to configure the same thing manually. I've tried the following:
#Configuration
#EnableTransactionManagement
public class PersistenceConfig
{
#Bean
public DataSource dataSource()
{
DataSource dataSource = new DataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/mywebapp");
dataSource.setUsername("username");
dataSource.setPassword("password");
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory()
{
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("com.example.persistent");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "validate");
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager()
{
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
}
...but while no exceptions are thrown and i can now successfully read from the database, it seems that none of the changes I make to the entities are being persisted.
Does anyone have an idea what I'm missing for the persistence to work?
OP here.
I seem to have misunderstood that JPA needs an EntityManager instead of a session.
The following configuration works:
#Configuration
#EnableTransactionManagement
public class PersistenceJpaConfig
{
#Bean
public DataSource dataSource()
{
DataSource dataSource = new DataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/mywebapp");
dataSource.setUsername("username");
dataSource.setPassword("password");
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.example.persistent");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.setProperty("hibernate.hbm2ddl.auto", "validate");
em.setJpaProperties(properties);
return em;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf)
{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
{
return new PersistenceExceptionTranslationPostProcessor();
}
}
I have created configuration using below code :
#Configuration
#EnableTransactionManagement
#ComponentScan("Name of package")
#EnableJpaRepositories("Name of package")
public class Config {
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "Name of package";
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("Driver Name");
dataSource.setUrl("Url");
dataSource.setUsername("UserName");
dataSource.setPassword("Password");
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN);
entityManagerFactoryBean.setJpaProperties(hibProperties());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return entityManagerFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, "org.hibernate.dialect.DB2Dialect");
properties.put("hibernate.default_schema","Schema Name");
return properties;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
}
There is an custom repository interface that implements JPARepository.
I have autowired the custom repository in controller and tried to call findAll().But the method returns 0 although there are 3 records in DB.
I am using spring web for rest service calls.
Entity class is created with #Entity and #Table annotations.It has an embedded key which is annotated using #EmbeddedId annotation.
#Repository
public interface EntityRepository extends JpaRepository<EntityTable, Long> {
#SuppressWarnings("unchecked") EntityTable save(EntityTable entityTable);
}
Entity table is the name of my table mapped with db table.