JPA EntityManager reject to work after database restart - java

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;
}

Related

Atomikos or DataSource transaction manager with multiple datasource and local transaction

My application works with multi datasources and 2 databases Oracle and PostgreSQL (I dont need global transaction) .
I dont know which transaction manager to use. Both have some advantages and disadvantages.
Atomikos suppport global transaction which I dont need and log some information about transaction to file system which I want to avoid:
public void setEnableLogging(boolean enableLogging)
Specifies if disk logging should be enabled or not. Defaults to true.
It is useful for JUnit testing, or to profile code without seeing the
transaction manager's activity as a hot spot but this should never be
disabled on production or data integrity cannot be guaranteed.
advantages is that it use just one transaction manager
When using DataSourceTransactionManager I need one per dataSource
#Bean
#Primary
DataSourceTransactionManager transactionManager1() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource1());
return transactionManager;
}
#Bean
DataSourceTransactionManager transactionManager2() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource2());
return transactionManager;
}
this is problem because I need to specify name of tm in annotation:
#Transactional("transactionManager1")
public void test() {
}
but I dont know it because in runtime I can switch in application which database to use.
is there some other options or I am missing something in this two transaction manager ?
You should solve this as option 2, using one DataSourceTransactionManager per data source. You will need to keep track of the transaction manager for each data source.
One thing additionally, if you need to be able to rollback transactions on both databases, you will have to set up a ChainedTransactionManager for both.

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.

How to kill Hibernates database connections in Spring boot 1.5.2?

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

Spring Boot - Persist transaction directly to embedded database

I use Spring Boot Jpa in a standalone GUI (Swing) java application with an embedded H2 database.
I use Spring Boot 1.3.0 and this is my additional configuration:
private static final String dataSourceUrl = "jdbc:h2:./databse;DB_CLOSE_ON_EXIT=FALSE";
#Bean
public DataSource dataSource() {
return DataSourceBuilder.create().url(dataSourceUrl).username("user").password("pwd").build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(new String[] { "packages.to.scan" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
em.setJpaProperties(properties);
return em;
}
In my application.properties file I have only one line: spring.aop.proxy-target-class=true.
For my repositories I extend JpaRepository.
Everything is working, the only problem I had recently: On a MAC which was running the application the MAC had some kind of problems and crashed. Afterwards none of the modification which was done before was actually stored in the database. I use the #Transactional annotation to modify data in the database.
I'm not very experienced with databases but after googling around I guess the transactions are cached by the persistence context (not sure if the terminology is correct) and is actually persisted when the application is closed. I checked the database file and made some manipluation through the GUI (includes also some queries) but the modification date of the database file changed only when I closed the application.
As this is a standalone GUI application there will be no performance issues if every transaction will be directly perisisted in the database. Am I on the correct way and how could I achieve that every transaction is directly persisted in the database? Are there any configuration I have to do or do I have to add any code after every call of the save() method of a repository?
If not, I have absolutely no idea how to debug this kind of problems as I have to admit that I'm not pretty sure whats actually going on under the hood..
Hibernate decides on it's own when to write to database (flushing the persistence context) based on optimization parameters and configured flushing strategy.
Maybe you can take a look here and adjust the behavior according to your needs:
https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch03.html
Information about the flush modes will also help you:
http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/FlushMode.html
Springs #Transactional follows the container managed transaction paradigm. By default if one #Transactional invokes a #Transactional method in another Componet/service/repository the transaction is propagated. When the outermost #Transactional method completes the transaction will be committed to the database.
JPA may flush data to the database multiple time within the same transaction, but everything in the transaction is either committed or rolled back when the transaction completed. If you have #Transactional on a #Controller, the transaction completes after the DispatchServlet has called the handler method (More specifically it happens indside the GCLIB or JDK Proxy which is created using Spring AOP)

How can I make a Spring Boot project with multiple data sources?

I'm working on a Spring Boot/Spring Batch project, and I need to configure two data sources. One is an in-memory hsqldb database used for tracking transactions. The other is a regular MySQL database which will be updated by my ItemWriters.
The problem is that as soon as I try to configure the second datasource, Spring starts throwing 'unresolvable circular dependency' errors, i.e.
Error creating bean with name 'preprodDataSource' defined in class path
resource [xxx/tools/batch/xxx/MyConfiguration.class]: Initialization of
bean failed; nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error
creating bean with name 'dataSourceAutoConfigurationInitializer': Requested bean is
currently in creation: Is there an unresolvable circular reference?
The relevant chunk of my MyConfiguration.java file looks like:
#Bean
public DataSource transactionsDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true;hsqldb.tx=mvcc");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
#Bean
public DataSource preprodDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/somedb");
dataSource.setUsername("someuser");
dataSource.setPassword("somepass");
return dataSource;
}
If I comment out the #Bean defining the second data source, everything is fine. The application starts up and runs without problems. However, if I leave it in, I get the error above.
My naive interpretation of this is that Spring is building an instance of 'dataSourceAutoConfigurationInitializer' to handle initialization of the first datasource and that when it tries to construct a second to handle the second datasource, bad things happen.
Is there any way to work around this?
By default, Spring Boot's auto-configuration will try to create a JdbcTemplate for you using your application's DataSource. As you have configured two, it doesn't know which one to use. To tell it which one to use you should mark one of them as #Primary:
#Bean
#Primary
public DataSource transactionsDataSource() {
BasicDataSource dataSource = new BasicDataSource();
…
return dataSource;
}
Alternatively, you could disable the auto-configuration.

Categories