Spring Boot with DB2 HADR ACR config - spring-boot

Is there a solution that is configured driver properties in the application.properties file?
DB2 HADR using clientRerouteAlternateServerName, clientRerouteAlternatePortNumber, enableClientAffinitiesList to indicate alternate server info.
I tried use below code to config datasource.
```
#Bean
public DataSource initds(){
Properties p = new Properties();
p.setProperty("user", "user");
p.setProperty("password", "password");
p.setProperty("clientRerouteAlternateServerName", "172.30.1.60,172.30.1.61");
p.setProperty("clientRerouteAlternatePortNumber", "53000,53000");
p.setProperty("enableClientAffinitiesList", "1");
DriverManagerDataSource dmds = new DriverManagerDataSource();
dmds.setDriverClassName("com.ibm.db2.jcc.DB2Driver");
dmds.setConnectionProperties(p);
dmds.setUrl("jdbc:db2://172.30.1.60:53000/dbsam");
return dmds;
}
```

Related

Hikari with Postgress datasource

What is the correct way to define hikari datasource in spring boot application ?
We are using this which works but I am not sure what PG datasource is used
datasource.test.jdbcUrl=url
datasource.test.username=username
datasource.test.password=pass
datasource.test.driver-class-name=org.postgresql.Driver
datasource.test.connection-test-query=SELECT 1
datasource.test.maximum-pool-size=5
with
HikariConfig config = new HikariConfig(props);
HikariDataSource ds = new HikariDataSource(config);
according to hikari README they are using ds with properties:
Properties props = new Properties();
props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
props.setProperty("dataSource.user", "test");
props.setProperty("dataSource.password", "test");
props.setProperty("dataSource.databaseName", "mydb");
...
where is defined PG datasource.
Is there any different between this two definition or I should used second one which is in Hikari wiki ? First one also use PGSimpleDataSource ?

How to set configuration using application.properties in Hibernate?

I am new to Spring boot development.
What I did?
I tested the sample MySQL integration with Spring boot and tested it works fine.
What I am trying?
I am trying to use Hibernate APIs with my existing project. So I create a util class for creating Hibernate sessionFactory.
My code:
public static void initSessionFactory() {
System.out.print("initSessionFactory");
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration();
//***** I don't want configuration here. ******
// Hibernate settings equivalent to hibernate.cfg.xml's properties
//Properties settings = new Properties();
// settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
// settings.put(Environment.URL, "jdbc:mysql://localhost:3306/hibernate_db?useSSL=false");
// settings.put(Environment.USER, "root");
// settings.put(Environment.PASS, "root");
// settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
// settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
// settings.put(Environment.HBM2DDL_AUTO, "create-drop");
// settings.put(Environment.SHOW_SQL, "true");
// configuration.setProperties(settings);
//configuration.addAnnotatedClass(Student.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
} catch (Exception e) {
e.printStackTrace();
}
}
}
My application.properties:(It works fine for without Hibernate)
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/tcc
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
My problem:
I already configured the jdbc environment & other configuration in my application.properties. It works fine. So I don't want to repeat the same configuration in my Java code. So I commented this configuration.
But without Java configuration it throws "The application must supply JDBC connections" error.
My Question:
How to set configuration from application.properties for Hibernate?
When you set the properties below in your app.properties, the Spring Boot will already make your DB connection ready when the application start.
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
You do not need to create SessionFactory , ServiceRegistery etc. even if you do not want to manage DB connection manually.
This link also explain the steps in more detail. You will see that there is no any custom bean, factory or registerer to establish DB connection. Please see it.
https://spring.io/guides/gs/accessing-data-mysql/

PostgreSQL open connection takes too long

I am currently developing a project using the following libs/frameworks:
hibernate: 5.2.11.Final
spring: 5.0.2.RELEASE
postgresql: 9.4.1212
mysql: 5.1.31
spring-data-jpa: 2.0.2.RELEASE
The project should be available in both Postgres and mysql. I am also using a profiler program called "Prefix" to track possible performance issues.
I realized that all my queries on postgresql were taking longer than the ones made on mysql, so I decided to look on profiler what was the issue.
Whenever I tried to establish a new connection to the database on mysql (DriverManager.getConnection), it took something between 5~10ms, and the same connection to postgresql is taking about 200ms+.
Do you guys know what could be making driver connections on postgresql take longer than mysql?
Here is how the db is configured:
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
dataSource.setDriverClassName(org.postgresql.Driver);
...
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("spring.jpa.hibernate.ddl-auto", props.getHibernateJPAAutoConfig());
if (props.getDatabaseName().equals(ProjectConstants.DATABASE_POSTGRE)) {
properties.put("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.PostgreSQL9Dialect");
properties.put("spring.jpa.properties.hibernate.jdbc.use_get_generated_keys", true);
properties.put("spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults", false); //started using those properties because I read that it could make postgresql connections faster; however it did not work.
}
return properties;
}
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource());
factory.setJpaProperties(hibernateProperties());
...
}

spring data jpa (hibernate+spring+jpa)

I got one requirement where each company has separate database with the same schema, in future new company might be added to same schema structure.I have to connect their company schema based on user login. So that I have to connect separate database each time when user login.I wan to use spring data JPA to take care of connection.Only I will configure new schema credential in properties file.Is there any way we can add dynamic database schema which uses same model classes.All should happen in run time only.
Sounds like you are asking about multi-tenant support. You can create a LocalContainerEntityManagerFactoryBean something like this:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver tenantIdentifierResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan(Application.class.getPackage().getName());
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
Map<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
// Improved naming strategy deprecated as of hibernate 5.0
// jpaProperties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
jpaProperties.put("hibernate.implicit_naming_strategy", "org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl");
jpaProperties.put("hibernate.physical_naming_strategy", "com.example.config.HibernateLegacyImprovedNamingStrategy");
jpaProperties.put("hibernate.show_sql", "true");
jpaProperties.put("hibernate.format_sql", "true");
jpaProperties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
jpaProperties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
jpaProperties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantIdentifierResolver);
emfBean.setJpaPropertyMap(jpaProperties);
return emfBean;
}
And provide implementations of MultiTenantConnectionProvider and CurrentTenantIdentifierResolver
As an example, for schema tenancy, the CurrentTenantIdentifierResolver could look up the current user from session to determine what schema to use.
The MultiTenantConnectionProvider could alter the connection with a command like SELECT set_schema_to(?) before returning the connection for use (and reset it on return).
#Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
setSchemaTo(connection, tenantIdentifier);
return connection;
}
You'll need to read up on multi-tenancy and see what type you want along with which implementations you are using.

Managing deployment-specific configurations with Spring

What strategies have people developed for controlling deployment configurations with Spring? I've already extracted out the environmental details (e.g. jdbc connection parameters) into a properties file, but I'm looking for some way of managing deployment details that aren't simple strings. Specifically, I'm currently using a locally configured datasource while doing development, and JNDI on our application servers (DEV, QA).
I've got an applicationContext.xml with the following two lines,
<import resource="spring/datasource-local-oracle.xml"/>
<import resource="spring/datasource-jndi.xml"/>
and I comment out whichever datasource isn't being used in that instance. There's got to be a better way to do this though. Thoughts, ideas, suggestions?
Use #Bean to define your datasource in code, rather than in XML. That way you can apply conditional logic to how the bean is created. For example:
#Value("${url:jdbc:hsqldb:mem:memdb}")
String url;
// username, password, etc
#Value("${jndiName:}")
String jndiName;
#Bean
public DataSource dataSource() {
DataSource ds;
if (jndiName == "") {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(driverClassName);
bds.setUrl(url);
bds.setUsername(username);
bds.setPassword(password);
ds = bds;
} else {
JndiObjectFactoryBean = jndiFactory = new JndiObjectFactoryBean();
jndiFactory.setJndiName("java:/" + jndiName);
jndiFactory.afterPropertiesSet();
ds = (DataSource) jndiFactory.getObject();
}
return ds;
}

Resources