Get SessionFactory on Java based configured Spring App - java

I need to upload an image to a database (not sure yet if is a good idea to do this or upload the file and reference it from the database) and I've defined a form and a controller to do that. The problem is that I need to convert the MultipartFile to a Blob object and for that I need to use Hibernate.getLobCreator who needs a Session object.
This is the first time using Java based config and I have the next class to define the persistence context:
#Configuration
#EnableJpaRepositories(basePackages = {
"com.davidmogar.alsa"
})
#EnableTransactionManagement
public class PersistenceContext {
private static final String[] ENTITY_PACKAGES = {
"com.davidmogar.alsa.domain"
};
private static final String PROPERTY_NAME_DB_DRIVER_CLASS = "db.driver";
private static final String PROPERTY_NAME_DB_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DB_URL = "db.url";
private static final String PROPERTY_NAME_DB_USER = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
private static final String PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = "hibernate.ejb.naming_strategy";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
#Bean(destroyMethod = "close")
DataSource dataSource(Environment environment) {
HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDriverClassName(environment.getRequiredProperty(PROPERTY_NAME_DB_DRIVER_CLASS));
dataSourceConfig.setJdbcUrl(environment.getRequiredProperty(PROPERTY_NAME_DB_URL));
dataSourceConfig.setUsername(environment.getRequiredProperty(PROPERTY_NAME_DB_USER));
dataSourceConfig.setPassword(environment.getRequiredProperty(PROPERTY_NAME_DB_PASSWORD));
return new HikariDataSource(dataSourceConfig);
}
#Bean(name = "entityManagerFactory")
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource, Environment environment) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan(ENTITY_PACKAGES);
Properties jpaProperties = new Properties();
jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty
(PROPERTY_NAME_HIBERNATE_DIALECT));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO, environment.getRequiredProperty
(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY, environment.getRequiredProperty
(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, environment.getRequiredProperty
(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty
(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
How can I get the Session in the controller to convert the MultipartFile?

You can get an instance of Hibernate Session via EntityManager.
#Autowired
private EntityManagerFactory emf;
public void foo(){
EntityManager em = emf.createEntityManager();
Session session = em.unwrap(Session.class);
LobCreator lob = getLobCreator(session);
...
}

Related

Spring Boot two databases JPA

I have two Postgres databases and a SpringBoot application. I connect to each database and perform separate transactions on each successfully. This has working fine as long as I have been using normal queries on my secondary database.
Primary: powwow
secondary: pims
As soon as I try execute a native query on the secondary (pims) database, it thinks it is looking at the primary database (powwow).
e.g. This "merchants" table is on the secondary database (pims):
PSQLException: ERROR: relation "merchants" does not exist
If I run the same native query but over a table on the primary (powwow) database, it works fine. So I think there's a problem with my config where I define the secondary (pims) datasource.
If I run a non native query over the secondary (pims) database using a repository in the com.xxxx.powwow.entities.pims package, it works fine.
Question
How do I execute a native query using a dao in the com.xxxx.powwow.dao.pims package?
PersistencePimsAutoConfiguration.java
#Configuration
#PropertySource({"classpath:application.properties"})
#EnableJpaRepositories(
basePackages = {"com.xxxx.powwow.dao.pims", "com.xxxx.powwow.repositories.pims"},
entityManagerFactoryRef = "pimsEntityManager",
transactionManagerRef = "pimsTransactionManager")
public class PersistencePimsAutoConfiguration {
private Logger logger = LogManager.getLogger(PersistencePimsAutoConfiguration.class);
#Value("${spring.datasource1.jdbc-url}")
private String url;
#Value("${spring.datasource1.username}")
private String username;
#Value("${spring.jpa.hibernate.ddl-auto}")
private String hbm2ddl;
#Value("${spring.jpa.database-platform}")
private String platform;
#Value("${spring.jpa.properties.hibernate.dialect}")
private String dialect;
#Value("${spring.profiles.active}")
private String profile;
#Bean
#ConfigurationProperties(prefix="spring.datasource1")
public DataSource pimsDataSource() {
return DataSourceBuilder.create().build();
}
//#Bean(name = "pimsEntityManager")
#Bean
public LocalContainerEntityManagerFactoryBean pimsEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(pimsDataSource());
em.setPackagesToScan(new String[] {"com.xxxx.powwow.entities.pims"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hbm2ddl);
properties.put("hibernate.dialect", dialect);
em.setJpaPropertyMap(properties);
String host = null;
try {
host = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
logger.info("Setting spring.datasource1 (pims): hibernate.hbm2ddl.auto='"+hbm2ddl+"', platform='"+platform+"', url='"+url+"', username='"+username+"', host='"+host+"', profile='"+profile+"'.");
return em;
}
#Bean
public PlatformTransactionManager pimsTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(pimsEntityManager().getObject());
return transactionManager;
}
}
BookingHistoryReportDao.java (package com.xxxx.powwow.dao.pims)
#Component
#Transactional("pimsTransactionManager")
public class BookingHistoryReportDao {
private Logger logger = LogManager.getLogger(BookingHistoryReportDao.class);
#PersistenceContext
private EntityManager entityManager;
public void executeBookingHistoryReport(Date startDate, Date endDate, List<Integer> companyIds) {
final String sql = getSQLBookingHistoryReportDao();
try {
Query qry = entityManager.createNativeQuery(sql);
List<String> merchants = qry.getResultList();
logger.info("done");
} catch (Exception e) {
logger.error("Error executing query for BookingHistoryReport.", e);
logger.info(sql);
}
}
private String getSQLBookingHistoryReportDao() {
return "select company_name from Merchants limit 100";
}
}
I managed to get this working by using the PersistenceUnitName.
e.g.
set it in the config:
em.setPersistenceUnitName("pimsPersistenceUnit");
and reference in the DAO:
#PersistenceContext(unitName = "pimsPersistenceUnit")
private EntityManager entityManager;

Annotations #ActiveProfile doesn't work in a Spring app

I'm not using spring-boot in this app.
I'm testing profiles to use different datasource in integration tests.
I have entity User as follow:
#Table(name = "user_inf")
#Entity
#NamedQuery(name="User.findById", query="select u from User u where u.id=:id")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "userName", length = 25)
private String userName;
#Column(name = "userEmail", unique = true, length = 320)
private String userEmail;
}
for that entity I have the service and dao(Service only invokes dao method)
UserDao :
#Repository
#Transactional
public class UserDaoImpl implements UserDao {
#PersistenceContext
private EntityManager entityManager;
#Override
public User findById(Long id) {
TypedQuery<User> query = entityManager.createNamedQuery("User.findById", User.class);
query.setParameter("id", id);
return query.getSingleResult();
}
}
User service :
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UserDao userDao;
#Override
public User getUser(Long id) {
return userDao.findById(id);
}
}
#Configuration
#PropertySource(value = {"classpath:database/jdbc.properties"})
#EnableTransactionManagement
#ComponentScan({"com.example.test.repository", "com.example.test.service"})
public class SpringConfig {
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String ENTITY_MANAGER_PACKAGES_TO_SCAN = "com.example.test.entity";
#Autowired
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
#Bean
#Profile("test")
public DataSource dataSourceForTest() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.test.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
#Bean
public PlatformTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return transactionManager;
}
private HibernateJpaVendorAdapter vendorAdaptor() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource mainDataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
entityManagerFactoryBean.setDataSource(mainDataSource);
entityManagerFactoryBean.setPackagesToScan(ENTITY_MANAGER_PACKAGES_TO_SCAN);
entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
return entityManagerFactoryBean;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties jpaHibernateProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH, env.getProperty(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put("hibernate.hbm2ddl.auto", "none");
return properties;
}
}
Property file which is used for datasource and hibernate (jdbc.properties) contains following :
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdatabase
jdbc.username=Bruce
jdbc.password=givanchy
jdbc.test.url=jdbc:mysql://localhost:3306/testdatabase1
hibernate.max_fetch_depth = 3
hibernate.jdbc.fetch_size = 50
hibernate.jdbc.batch_size = 10
hibernate.show_sql = true
hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
Entry point for application :
public class EntryClass {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
User user =userService.getUser(1L);
System.out.println("userName is "+user.getUserName());
}
}
It works as it should.
But in test source
I have only one test for service to understand how profiles work
#SpringJUnitConfig(SpringConfig.class)
#ActiveProfiles("test")
class UserServiceImplTest {
#Autowired
private UserService userService;
#Test
void getUser() {
User user = userService.getUser(5L);
Assertions.assertEquals("Vector", user.getUserName());
}
}
And I get "No qualifying bean" exception because there are two beans of datasource type, but I set which profile it should use?Can you explain why It doesn't work?
When you launch it normally, the datasource bean with 'test' profile is not created. (becasue there is no test profile set.)
When you run it as a test, then both datasource beans are created. The default is created because there is no any condition on it, and the other is becasue its annotated with the test profile.
Simply add #Profile("!test") to the default bean. This way it will be created only if the test profile is NOT active.

Spring MVC backend returns 404 (Rest)

I hope someone can help me with my problem. I write at the moment a Spring MVC Server and a client. Unfortunatly my Rest Controller only returns a 404. I am using a Tomcat 8. What I know is that the Spring Application is deployed correctly because I can visit my index.jsp page. The context, under which it is deployed is /backend. So my base url is localhost:8080/backend. Now I have a restcontroller whitch looks like this.
#Controller
#RequestMapping("/api/developer")
public class DeveloperController {
#Autowired
private DeveloperOutboundDipatcher service;
#RequestMapping(method = RequestMethod.GET, value = "/getAll")
public List<DeveloperDTO> findAll() {
return service.findAllDeveloper();
}
#RequestMapping(method = RequestMethod.GET, value = "/get/{name}")
public DeveloperDTO findByName(#PathVariable String name) {
return service.findOneByName(name);
}
#RequestMapping(method = RequestMethod.DELETE, value = "/delete/{name}")
public void deleteDeveloper(#PathVariable String name) {
service.deleteDeveloper(name);
}
#RequestMapping(method = RequestMethod.POST, value = "/save/")
public void saveDeveloper(#RequestBody DeveloperDTO developer) {
service.save(developer);
}
#RequestMapping(method = RequestMethod.PUT, value = "/edit/")
public void editDeveloper(#RequestBody DeveloperDTO developer) {
service.edit(developer);
}
}
my config class looks like this:
package gamescreation;
#Configuration
#ComponentScan(basePackages= "gamescreation")
#EnableJpaRepositories("gamescreation")
#EnableTransactionManagement
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
private final String PROPERTY_DRIVER = "driver";
private final String PROPERTY_URL = "url";
private final String PROPERTY_USERNAME = "user";
private final String PROPERTY_PASSWORD = "password";
private final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
private final String PROPERTY_DIALECT = "hibernate.dialect";
#Autowired
Environment environment;
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("gamescreation.entity" );
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource ();
dataSource.setDriverClassName("org.postgresql.Driver");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(
EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
"false");
setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL82Dialect");
setProperty("hibernate.globally_quoted_identifiers",
"true");
}
};
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:/db-changelog-master.xml");
liquibase.setDataSource(dataSource());
return liquibase;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
I hope someone can tell me what is missing.
My client class looks like this:
#Service
public class DeveloperService {
private static final String DEVELOPER_BASEURL = "http://localhost:8080/backend/api/developer";
public List<DeveloperDTO> getDeveloperList() {
RestTemplate restTemplate = new RestTemplate();
DeveloperList response = restTemplate.getForObject(DEVELOPER_BASEURL + "/getAll", DeveloperList.class);
return response.getDevelopers();
}
public DeveloperDTO getSelectedDeveloper(String name) {
String url = DEVELOPER_BASEURL + "/get/{name}";
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("name", name);
RestTemplate restTemplate = new RestTemplate();
DeveloperDTO response = restTemplate.getForObject(builder.toUriString(), DeveloperDTO.class);
return response;
}
public void delete(String name) {
String url = DEVELOPER_BASEURL + "/delete/{name}";
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("name", name);
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(builder.toUriString());
}
public DeveloperDTO save(DeveloperDTO dto) {
String url = DEVELOPER_BASEURL + "/save";
HttpEntity<DeveloperDTO> request = new HttpEntity<>(dto);
RestTemplate restTemplate = new RestTemplate();
DeveloperDTO response = restTemplate.postForObject(url, request, DeveloperDTO.class);
return response;
}
}
Thank you in advance for your help. If you need any other information from my project, feel free to ask.
#Controller alone will not work please use #Responsebody to get the response in REST or use the #RestController.

hibernate didn't auto update the #ElementCollection

According to the book when i update a ElementCOllection List , i do not do the Transection.begin, the hibernate will auto commit, but i made a test on it, the result has something wrong
My Main.java is
public class Main {
private static UserService userService;
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(RootConfig.class);
userService = applicationContext.getBean(UserService.class);
User user = new User("qwerty");
user.getMessages().add("hello,world");
userService.save(user);
User user1 = userService.findByName("qwerty");
user1.getMessages().add("ncjdksckds");
System.out.println(user);
}
}
and my configuration is here , coding according the book
#Configuration
#ComponentScan(basePackages = {"org.zhy"})
#EnableJpaRepositories(basePackages = {"org.zhy.repository"})
#EnableTransactionManagement
public class RootConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter ) {
LocalContainerEntityManagerFactoryBean emfb =
new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(dataSource);
emfb.setJpaVendorAdapter(jpaVendorAdapter);
emfb.setPersistenceUnitName("demo");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
emfb.setJpaProperties(hibernateProperties);
emfb.setPackagesToScan("org.zhy.domain");
return emfb;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
// some setting here such as url...
return ds;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setGenerateDdl(false);
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(true);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
return adapter;
}
}
the Entity is here
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ElementCollection(fetch = FetchType.EAGER)
private List<String> messages = new ArrayList<String>();
//getter and setter
when i use user1.getMessages().add("ncjdksckds");
the database did not auto flush the new message into it , i want to know why????
Not sure which book you are referring to but the key about #ElementCollection in your case is that all operations are cascaded by default.
Assuming your service has all public methods marked as transactional, after you query for the user, it is a detached entity.. as it is from now on outside of any transactional scope.
In your code:
User user = new User("qwerty");
user.getMessages().add("hello,world");
userService.save(user); // new transaction start and finish
User user1 = userService.findByName("qwerty"); // new transaction start and finish
user1.getMessages().add("ncjdksckds"); // this change is outside of a transaction
in order to make that change persistend you would need to merge the user1 entity back into the persistence context:
userService.merge(user1);
Inside you would call:
entityManager.merge(user);

Number of connections are not same as connection pool size in config for JPA

I am Spring Boot in my application and using C3P0 for connection pools. Even a freshly booted application shows ~14 connection when I query the database
SELECT usename, count(*) as count FROM pg_stat_activity group by usename
When I give some load on the application, then it reaches the count specified in the config + ~14 connections. I am not sure from where these connections are open.
Here is my config file for initializing the database.
public class PgDataSourceConfig {
#Autowired
JpaVendorAdapter jpaVendorAdapter;
#Autowired
DataSource dataSource;
#Value("${spring.datasource.url}")
private String databaseUrl;
#Value("${spring.datasource.username}")
private String username;
#Value("${spring.datasource.password}")
private String password;
#Value("${pg.import_files}")
private String importFiles;
#Value("${pg.hbm2ddl.auto}")
private String hbm2Ddl;
#Value("${pg.default_schema}")
private String default_schema;
#Value("${hibernate.jdbc.batch_size}")
private String batch_size;
#Value("${hibernate.c3p0.max_size}")
private String max_size;
#Value("${hibernate.c3p0.min_size}")
private String min_size;
#Value("${hibernate.c3p0.timeout}")
private String timeout;
#Value("${hibernate.c3p0.max_statements}")
private String max_statements;
#Value("${hibernate.c3p0.idle_test_period}")
private String idle_test_period;
#Value("${hibernate.c3p0.acquire_increment}")
private String acquire_increment;
#Value("${hibernate.c3p0.validate}")
private String validate;
#Value("${pg.format_sql}")
private String formatSql;
#Value("${pg.use_sql_comments}")
private String useSqlComments;
#Bean
#DependsOn(value = {"flyway"})
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
Properties properties = new Properties();
properties.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL9Dialect");
properties.setProperty("hibernate.hbm2ddl.auto", hbm2Ddl);
properties.setProperty("hibernate.connection.url", databaseUrl);
properties.setProperty("hibernate.connection.username", username);
properties.setProperty("hibernate.connection.password", password);
properties.setProperty("hibernate.hbm2ddl.import_files", importFiles);
properties.setProperty("hibernate.format_sql", formatSql);
properties.setProperty("hibernate.use_sql_comments", useSqlComments);
properties.setProperty("hibernate.jdbc.batch_size", batch_size);
properties.setProperty("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
properties.setProperty("hibernate.c3p0.max_size", max_size);
properties.setProperty("hibernate.c3p0.min_size", min_size);
properties.setProperty("hibernate.c3p0.timeout", timeout);
properties.setProperty("hibernate.c3p0.max_statements", max_statements);
properties.setProperty("hibernate.c3p0.idle_test_period", idle_test_period);
properties.setProperty("hibernate.c3p0.acquire_increment", acquire_increment);
properties.setProperty("hibernate.c3p0.validate", validate);
properties.setProperty("hibernate.id.new_generator_mappings", "true");
final LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setDataSource(dataSource);
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
localContainerEntityManagerFactoryBean.setPackagesToScan("com.test");
localContainerEntityManagerFactoryBean.setPersistenceUnitName("default");
localContainerEntityManagerFactoryBean.setJpaProperties(properties);
localContainerEntityManagerFactoryBean.afterPropertiesSet();
return localContainerEntityManagerFactoryBean;
}
#Bean(name = "entityManager")
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
#Primary
#Bean(name = "entityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean emf = this.entityManagerFactoryBean();
return emf.getObject();
}
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(entityManagerFactory());
return tm;
}
}
And these are the values from properties file
spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.username=ashwani
spring.datasource.password=ashwani
pg.import_files=lookup.sql,data.sql
pg.hbm2ddl.auto=validate
hibernate.c3p0.max_size= 10
hibernate.c3p0.min_size= 1
hibernate.c3p0.timeout =10
hibernate.c3p0.max_statements =100
hibernate.c3p0.idle_test_period =3
hibernate.c3p0.acquire_increment =1
hibernate.c3p0.validate =false
hibernate.jdbc.batch_size=25
I am not sure what is wrong in the configuration which results in extra connections.
How can I fix this?
Thanks

Categories