SpringBoot + Maven connects and create database schema - mysql

It's there anyway to create a springboot application that whent it runs for the first time, connect to mysql, and creates the database schema if it do not exists?
I'm using this configuration:
#Configuration
public class DataConfiguration {
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/dbname");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setGenerateDdl(true);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
adapter.setPrepareConnection(true);
return adapter;
}

Sure,
Spring boot already has an integration with Flyway and Liquidbase.
For example, Flyway allows creating the schema and running a series of database migrations upon the first run.
If the migrations are already done, flyway won't change the database schema.
This tool is really powerful and you can configure it to run when the spring boot application starts.
Check This document for more information about spring boot integration with database related tools

Related

Why the second database not created when multiple datasources in Springboot application?

I want to use two (Mysql) databases in my Springboot application. Following the instructions I use the following configuration
app.properties
spring.datasource.url = jdbc:mysql://localhost:3306/db1?createDatabaseIfNotExist=true&autoReconnect=true
spring.datasource.username = root
spring.datasource.password = password
spring.seconddatasource.url = jdbc:mysql://localhost:3306/db2?createDatabaseIfNotExist=true&autoReconnect=true
spring.seconddatasource.username = root
spring.seconddatasource.password = password
DataSourceConfig.java
#Configuration
public class DataSourceConfig {
#Bean("dataSource")
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create()
.type(DriverManagerDataSource.class)
.build();
}
#Bean("secondDataSource")
#ConfigurationProperties(prefix = "spring.seconddatasource")
public DataSource secondDataSource() {
return DataSourceBuilder.create()
.type(DriverManagerDataSource.class)
.build();
}
}
The application starts without errors but only the first database (or whichever datasource bean is marked as primary) gets created. Why not the second?
EDIT:
Once I create the second database manually, the application connects to both of them just fine. It is the automatic creation of the non-primary database only that is causing the problems.
Because you're using #ConfigurationProperties wrong. The annotation most certainly does not point a bean to the relevant configuration. The first DB gets created because, well, spring.datasource.* are actually standard Spring Boot properties.
If you wish to create two data sources, at the very least you'll need to set the appropriate properties (url, password) on the second one yourself. You may inject your custom properties (spring.seconddatasource.*) into the configuration class using #Value, of course.

How to configure spring-kafka's partition and replication in distributed environment?

I want to configure 3 partitions and 3 replications of a topic in distributed environment with three nodes. How can I configure these by java api without shell command?
If I have three nodes: node1, node2 and node3. I want partition1 and replication3 are deployed in node1, partition2 and replication1 are deployed in node2, partition3 and replication2 are deployed in node3.
I've tried spring-kafka's api in single-machine environment, this can create a topic and 1 partition automatically. But it not work in distributed environment.
My maven configuration is:
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>1.1.7.RELEASE</version>
</dependency>
1.1.x is no longer supported; you should be using at least 1.3.9.
1.3.x comes with KafkaAdmin, which can automatically configure any NewTopic beans in the application context.
See Configuring Topics.
If you define a KafkaAdmin bean in your application context, it can automatically add topics to the broker. Simply add a NewTopic #Bean for each topic to the application context.
#Bean
public KafkaAdmin admin() {
Map<String, Object> configs = new HashMap<>();
configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG,
StringUtils.arrayToCommaDelimitedString(kafkaEmbedded().getBrokerAddresses()));
return new KafkaAdmin(configs);
}
#Bean
public NewTopic topic1() {
return new NewTopic("foo", 10, (short) 2);
}
#Bean
public NewTopic topic2() {
return new NewTopic("bar", 10, (short) 2);
}

Spring + MyBatis - setting Data Source

I'm integrating MyBatis inside my SpringBoot application. The application connects to a MySql database to fetch data. Right now I have the following classes.
MyBatisUtils.java
[...]
#Component
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(getConfiguration());
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
private static Configuration getConfiguration(){
Configuration configuration = new Configuration();
DataSource dataSource = null; //wrong!!!
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
configuration.addMapper(BaseQuery.class);
return configuration;
}
}
Search.java
[...]
public List dynamicSearch(){
SqlSession session = MyBatisUtils.getSqlSessionFactory().openSession();
BaseQuery mapper = session.getMapper(BaseQuery.class);
List<HashMap<String, Object>> result = mapper.select(/*query parameters*/);
return result;
}
I do not know how to set my DataSource object inside the MyBatisUtils class. Should it have some connection parameters?
Thanks for the help.
Define the DataSource as a Spring bean, like in this other question:
How to Define a MySql datasource bean via XML in Spring
Then inject the datasource in MyBatisUtils class.
You can also define SqlSessionFactory as a Spring bean, and directly inject it. Useful reference: http://www.mybatis.org/spring/getting-started.html
If you are using spring-boot already you can use mybatis-spring-boot-starter and auto-configure mybatis for free. The only thing you should worry about is the datasource. For that, properties should be set in application.properties
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
You can find more info here

DataSourceInitializer is not working on Spring boot 1.2

I am new to Spring boot.I want to add some sql while database is creating like seed data.
#Value("classpath:com/foo/sql/db-test-data.sql")
private Resource dataScript;
#Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator());
return initializer;
}
private DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(dataScript);
return populator;
}
props.put("hibernate.query.substitutions", "true 1, false 0");
props.put("hibernate.hbm2ddl.auto", "create-drop");
props.put("hibernate.show_sql", "false");
props.put("hibernate.format_sql", "true");
I have perform this action.But it not working on spring boot.Can any one help me.
Sometimes spring-boot gets more in the way than it helps; IMHO this is especially so with web applications.
What you can do to get around this is to rename the bean that you define.
#Bean("springBootPleaseStopTellingMeHowYouThinkDataSourceInitializer")
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
// build it.
}
Now, to turn off the built in bit that looks for data.sql in application.properties
spring.datasource.initialize=false
There, now boot is booted out of the way.
You can take advantage of Spring Boot database initialization capabilities. The simplest way is to place a "data.sql" file in the root of the classpath. So you just need to:
Change your sql file name to "data.sql".
Place it in "src/main/resources".
Spring Boot will automatically pick up the file and use it to initialize the database on startup.
You can check the documentation if you need to customize the file name, location, etc.

Spring Data JPA in two repositories for databases

I want to use spring data jpa repository. And I have to connect to 2 databases. I already found so many similar questions. But most of answers are using Entity manager instead of repository.
For example
#persistenceContext(unitname = "example")
Entitymanager em;
But I want to use repository of spring data jpa. How can I configure in applicationContext.xml?
My 2 databases are MySQL and one is local another is remote server.
You can separate those repositories in different packages. Then its possible to create two DB's configurations with different enity manager factory and transaction manager.
For example first config:
#Configuration
#EnableJpaRepositories(basePackages = "com.firstpackage",
entityManagerFactoryRef = "entityManagerFactoryDb1",
transactionManagerRef = "transactionManagerDb1")
public class DB1Config {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryDb1() {
...
}
public JpaTransactionManager transactionManagerDb1() {
...
}
public DataSource dataSourceDb11() {
...
}
Second config would be similar.
You didnt put many details in question, but in case you need to switch databases for same repositories ( for example for different locales ) you can use AbstractRoutingDataSource class which will define determineCurrentLookupKey method.