How to kill Hibernates database connections in Spring boot 1.5.2? - java

The problem is simple when I use Spring boot 1.5.2 with Hibernate to connect to a datasource with configued like this:
#Bean
public DataSource dataSource() {
DataSourceBuilder = datasourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url(DATASOURCE_URL);
dataSourceBuilder.username(DATASOURCE_USERNAME);
dataSourceBuilder.password(DATASOURCE_PASSWORD);
return dataSourceBuilder.build();
}
and this is a Command line application, so when the application is almost done, I just want to close the Hibernate connections to the database and rename the database with JDBC. However, I don't know how to do this in Spring boot, any idea?
I tried to inject the DataSource object to a class to rename database but it cannot close the connections to database.
#Autowired
private DataSource dataSource;
public void closeConnection() {
dataSource.close();
}
with error
org.postgresql.util.PSQLException: ERROR: database "DATABASE" is being accessed by other users
Detail: There are 10 other sessions using the database.

You can use pg_terminate_backend() to kill a connection. You have to be superuser to use this function. This works on all operating systems the same.
refer this stackoverflow link :
https://stackoverflow.com/a/5109190/7801800

Related

How to configure #Transactional support to Redis in Springboot?

I am currently working on a project which is using Redis mainly for caching purposes, I am using Oracle as the main database and Spring Data JPA to handle the database layer in my project. I need to know how to use #Transactional annotation support to handle transactions in Redis. I have already referred to lots of tutorials and documentation regarding this scenario. In most of those tutorials, there is always the same set of source codes available. But still, I didn't have a clear idea about the implementation. Because in my application there is already a data source available which I configured through property file. (Oracle database) So I doubt the implementation of the dataSource bean. And I couldn't understand the usage of transactionManager bean too. How should I implement this properly please give a detailed explanation.
Source code which I found on the internet.
#Configuration
#EnableTransactionManagement // 1
public class RedisConfig {
#Bean
public StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {
// Configure redisTemplate
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
/ / Open transaction support
stringRedisTemplate.setEnableTransactionSupport(true); // 2
return stringRedisTemplate;
}
#Bean
public PlatformTransactionManager transactionManager() throws SQLException {
return new DataSourceTransactionManager(dataSource()); // 3
}
#Bean
public DataSource dataSource() throws SQLException {
// ...
}
}
Updated :
Currently configured datasource properties in apppication.properties file.
# OracleDB connection settings
spring.datasource.url=jdbc:oracle:thin:#192.168.20.108:1521:orcl
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
# HikariCP settings
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.poolName=redis-sample-pool
Resource about the Redis Transactions handling
There're two ways to configure DataSource
Using the config file
spring.datasource.url= jdbc:oracle:thin:#//localhost
spring.datasource.username=test
spring.datasource.password=test1234
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
#hibernate config dialect for JPA, choose dialect based on the db version
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
You can create manually the same by reading these properties, with the help of DataSourceBuilder
#Bean
public DataSource dataSource(){
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("oracle.jdbc.OracleDriver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("test");
dataSourceBuilder.password("test1234");
return dataSourceBuilder.build();
}

Spring Data. Change DB user credentials at runtime

There is Spring Boot Aplication. For forking with DB I use Spring Data (JPA + Repository).
Is there way to change DB user-credentials for datasource per API user-request? I mean each MVC request must do his own work with exactly his DB user-credentials.
I've read info about AbstractRoutingDataSource. But there is limitation: there isn't possibility to add datasource at runtime in DataSourceMap.
In fact I want to use apache PerUserPoolDataSource and change DB user-credentials (using Spring Security Context to get user information)
I've found solution. First of all need to define custom datasource configuration.
#Bean
public UserCredentialsDataSourceAdapter dataSource() throws ClassNotFoundException {
final UserCredentialsDataSourceAdapter dataSourceAdapter = new UserCredentialsDataSourceAdapter();
dataSourceAdapter.setTargetDataSource(perUserPoolDataSource());
return dataSourceAdapter;
}
private PerUserPoolDataSource perUserPoolDataSource() throws ClassNotFoundException {
DriverAdapterCPDS driverAdapter = new DriverAdapterCPDS();
driverAdapter.setDriver(properties.getDriverClassName());
driverAdapter.setUrl(properties.getUrl());
driverAdapter.setUser(properties.getUsername());//default
driverAdapter.setPassword(properties.getPassword());//default
driverAdapter.setAccessToUnderlyingConnectionAllowed(true);
PerUserPoolDataSource dataSource = new PerUserPoolDataSource();
dataSource.setConnectionPoolDataSource(driverAdapter);
return dataSource;
}
As you see - there is base datasource from Apache: PerUserPoolDataSource.
Also as main datasource I will use UserCredentialsDataSourceAdapter.
Then need to write custom filter, which will change user credentials for successefully authenticated users:
dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword());
This solution works for blocked paradygm (not reactive). One thread with credentials for specific user will do all queries.

How does Spring deal with #Autowired on fields that required a parameter? In this case, JdbcTemplate with DataSource

I have a SpringBoot app that I want to connect to my MySQL database and I want to connect it with JDBC (by itself, not using JPA). And from what I have seen on articles, one way to achieve this is with JdbcTemplate and DataSource objects).
Now I have a RestController where I call my database, "CoffeeShop" which has me with the following class/code:
#RestController
public class MenuController {
#Autowired
private DataSource dataSource;
#Autowired
private JdbcTemplate jdbcTemplate;
private String menuQuery = "SELECT * FROM menu";
#CrossOrigin(origins = "http://localhost:4200")
#GetMapping(path="/menu")
public String getMenu(){
jdbcTemplate.query(menuQuery, (rs, rowNum) -> new Menu(rs.getString("name"))).forEach(
customer-> System.out.println(customer.getName()));
return "worked";
}
private List<Menu> organizeMenu() {
return null;
}
}
If my understanding is correct, I expect that dataSource will be able to see in my application.properties file the following contents when being compiled and then Spring figures out that jdbcTemplate requires it?:
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driverclassname = com.mysql.jdbc.Driver
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/CoffeeShop?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=springuser
spring.datasource.password=ThePassword
To my surprise this worked, my code queried the DB and logged the correct output. But I'm not sure how this worked since jdbcTemplate required dataSource?
See the Spring Boot Getting Started | Accessing Relational Data using JDBC with Spring guide, which says:
Spring Boot supports H2 (an in-memory relational database engine) and automatically creates a connection. Because we use spring-jdbc, Spring Boot automatically creates a JdbcTemplate. The #Autowired JdbcTemplate field automatically loads it and makes it available.
This is what you get with the auto-configuration provided by Spring Boot: Fully functional JdbcTemplate automatically created and configured from the application.properties file.
FYI: The JdbcTemplate is already configured to use the DataSource, so you don't need to auto-wire the DataSource. As you can see in your own code, the dataSource field isn't used anywhere, so you should remove it.
It is actually the DataSource that is auto-configured from the application.properties file.

JPA EntityManager reject to work after database restart

I have Spring Boot Application and I am using JPA EntityManager.
I run db and my application. While my application is running I stop and start my database.
After this actions, my application works like db is still stopped.
It always says that transaction is failed.
I must restart application to make it work. How to solve it?
UPDATE: Connection pool configuration
#Bean("dataSource")
#Singleton
public DataSource getDataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
basicDataSource.setUrl(environment.getProperty("url"));
basicDataSource.setUsername(environment.getProperty("user"));
basicDataSource.setPassword(environment.getProperty("password"));
basicDataSource.setInitialSize(5);
basicDataSource.setMinIdle(3);
basicDataSource.setMaxIdle(15);
basicDataSource.setMaxWait(10000);
basicDataSource.setMaxActive(100);
return basicDataSource;
}

java spring connect to mysql database (not JNDI pool or system datasource!)

I have a java spring application that uses it's postgres db, it's no prob. But also I have a quartz job that runs every hour and syncing data from other mysql DS with postgres. The issue is JDBC connection string is dynamic and is being changed, I can't just specify it on systemstartup, etc. How to do that gracefully? I mean take jdbc connection string, connect to db and retrieve data from there? I also use spring-data there.
One possible solution is to use spring batch #JobScope beans and have your quartz job launch the spring batch job.
You can configure a datasource to have #JobScope and this would then make spring create that datasource each time the job is executed. You can then use job parameters or other variables to create the specific datasource that you want. An example of a configuration class that creates a datasource like this is below...
#Configuration
public class JobDatabaseConfiguration {
#Bean
#JobScope
public DataSource jobDataSource() throws IOException {
// set these from job parameters...
String jdbcUrl = "<your jdbc url>";
String driver = "<your driver>";
String user = "user";
String password = "password";
return DataSourceBuilder.create()
.driverClassName(driver)
.url(jdbcUrl)
.username(user)
.password(password)
build();
}
}

Categories