hibernate 5 - Could not obtain transaction-synchronized Session for current thread; - java

I am able to use sessions if I open a new one, however, I am getting this error if I try to get the current session which I guess doesn't exist.
persistence-h2.properties
# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/my-database
jdbc.eventGeneratedId=sa
jdbc.user=root
jdbc.pass=root_password
# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=validate
# hibernate.search.X
hibernate.search.default.directory_provider = filesystem
hibernate.search.default.indexBase = /data/index/default
# envers.X
envers.audit_table_suffix=_audit_log
HibernateConfig.java
package com.buraktas.spring;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence-h2.properties" })
#ComponentScan({ "com.buraktas" })
public class HibernateConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.buraktas.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", "true");
// Envers properties
hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
return hibernateProperties;
}
}
PersonDaoImp.java
#Repository
public class PersonDaoImp implements PersonDao {
#Autowired
private SessionFactory sessionFactory;
public Person getPerson(int id) {
Session currentSession = sessionFactory.getCurrentSession();
return currentSession.get(Person.class, 1);
}
}
Here if I use sessionFactory.openSession() instead then I am able to query my database. But I don't want to create a new session and close it every time. I thought I needed to add current_session_context_class and connection.pool_size properties as well, but that didn't solve the problem. So long story short how I can initialize a connection pool or a session pool?
Thanks!

This is a late response, but as I mentioned in the comments adding #Transactional on class level worked.

Related

EntityManager doesn't translate camel case to snake case

I'm using SpringBoot 2.7.0 and trying to set an entity manager cause I have 2 databases.
But the entityManager that I instantiated doesn't work like default one.
It doesn't translate camel case to snake case for the properties of entity when it creates tables.
Even it doesn't follow the settings in application.yml. for example, spring.jpa.show-sql.
I configured it with below code.
#Slf4j
#RequiredArgsConstructor
#EnableJpaAuditing
#EnableJpaRepositories(basePackages = "com.xxx.yyy", entityManagerFactoryRef = "businessEntityManagerFactory", transactionManagerRef = "businessTransactionManager")
#EntityScan(basePackages = "com.xxx.yyy")
#Configuration
public class JpaConfiguration {
#Bean
public LocalContainerEntityManagerFactoryBean businessEntityManagerFactory(EntityManagerFactoryBuilder builder,
DataSource businessDataSource) {
return builder
.dataSource(businessDataSource)
.packages("com.xxx.yyy")
.build();
}
#Bean
public PlatformTransactionManager businessTransactionManager(LocalContainerEntityManagerFactoryBean businessEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(businessEntityManagerFactory.getObject()));
}
}
Does anyone know how I can instantiate an entity manager with same settings like spring boot default one?
Spring's convention-over-configuration does not work well with multiple database configurations.
Particuallary the configuration has to be autowired "manually". That's the reason springt.jpa.show-sql is not considered.
I will post an example on how to configure a database "manually".
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
#EnableTransactionManagement
#EnableAutoConfiguration(exclude = {JdbcRepositoriesAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class, DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
#EnableJpaRepositories(basePackageClasses = {ExampleXyzRepository.class}, transactionManagerRef = DatabaseConfig.SPRING_TRANSACTION_MANAGER)
public class DatabaseConfig {
public static final String SPRING_TRANSACTION_MANAGER = "springTransactionManager";
private static LocalContainerEntityManagerFactoryBean createEntityManagerFactory(
final ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider, final JpaProperties jpaProperties,
final HibernateProperties hibernateProperties, final DataSource dataSource, final Class<?> exampleEntityClass, final String persistenceUnit) {
return createEntityManagerFactoryBuilder(persistenceUnitManagerProvider.getIfAvailable(), jpaProperties, hibernateProperties)
.dataSource(dataSource)
.packages(exampleEntityClass)
.persistenceUnit(persistenceUnit)
.build();
}
private static EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(
final PersistenceUnitManager persistenceUnitManager, final JpaProperties jpaProperties, final HibernateProperties hibernateProperties) {
final JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
final Map<String, Object> expandedProperties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
return new EntityManagerFactoryBuilder(jpaVendorAdapter, expandedProperties, persistenceUnitManager);
}
private static JpaVendorAdapter createJpaVendorAdapter(final JpaProperties jpaProperties) {
final AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
if (jpaProperties.getDatabase() != null) {
adapter.setDatabase(jpaProperties.getDatabase());
}
return adapter;
}
private static HikariDataSource initializeDataSource(final DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
#ConfigurationProperties("spring.datasource")
public DataSourceProperties springDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.datasource.hikari")
public DataSource springDataSource(#Qualifier("springDataSourceProperties") final DataSourceProperties springDataSourceProperties) {
return initializeDataSource(springDataSourceProperties);
}
#Bean
#ConfigurationProperties("spring.jpa")
public JpaProperties springJpaProperties() {
return new JpaProperties();
}
#Bean
#ConfigurationProperties("spring.jpa.hibernate")
public HibernateProperties springHibernateProperties() {
return new HibernateProperties();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
final ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider,
#Qualifier("springJpaProperties") final JpaProperties springJpaProperties,
#Qualifier("springHibernateProperties") final HibernateProperties springHibernateProperties,
#Qualifier("springDataSource") final DataSource springDataSource) {
return createEntityManagerFactory(persistenceUnitManagerProvider, springJpaProperties, springHibernateProperties, springDataSource, ExampleXyzEntity.class, "default-persistence-unit");
}
#Bean(SPRING_TRANSACTION_MANAGER)
public JpaTransactionManager transactionManager(#Qualifier("entityManagerFactory") final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
See how the configuration of DataSourceProperties, HibernateProperties, DataSource and JpaProperties are bound.
The second database is configured similar.
But:
use a different configuration prefix and not spring.jpa and spring.datasource - obviously
define the transactionManager in the org.springframework.transaction.annotation.Transactional while accessing the second database, e.g. in the CrudRepository
Sven's answer might be right but I didn't try it because I saw this after I found the solution and it looked requiring many changes my codes.
I figured this out with below codes
#Bean
public LocalContainerEntityManagerFactoryBean businessEntityManagerFactory(DataSource businessDataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(businessDataSource);
emf.setPackagesToScan("com.xxx.yyy");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(Boolean.valueOf(env.getProperty("spring.jpa.show-sql")));
emf.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.format_sql", env.getProperty("spring.jpa.properties.hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.properties.hibernate.hbm2ddl.auto"));
properties.put("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy");
properties.put("hibernate.implicit_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
emf.setJpaPropertyMap(properties);
return emf;
}

Relationship between two entities of different schemes - Spring Boot Data JPA

Is it possible to cross join between two different database tables (2 DataSources) in Spring Boot using JPA? If so, how would you configure this configuration? In the application.properties, 4 databases are already being defined and 4 files have been created that represent the configurations of the DataSources. The scenario is that there is a DataSource 1 table that has a FOREIGN KEY with a DataSource 2 table, but when the application is raised an Exception is generated:
#OneToOne or #ManyToOne on com.smart4.bdcentral.domain.files.IndividuoFoto .persons references an unknown entity: com.smart4.bdcentral.domain.main.IndividuoPessoa
DataSource 1
package com.smart4.configBases;
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import com.google.common.base.Preconditions;
#Configuration
#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(basePackages = {"com.smart4.bdcentral.repository.main"},
entityManagerFactoryRef = "bdCentralMainEntityManager",
transactionManagerRef = "bdCentralMainTransactionManager")
public class BdCentralMain {
#Autowired
private Environment env;
public BdCentralMain() {
super();
}
#Bean
public LocalContainerEntityManagerFactoryBean bdCentralMainEntityManager() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(bdCentralMainDataSource());
em.setPackagesToScan(new String[] { "com.smart4.bdcentral.domain.main" });
em.setPersistenceUnitName("bdcentralmain");
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
em.setJpaVendorAdapter(vendorAdapter);
final HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("bdcentralmain.hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("bdcentralmain.hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource bdCentralMainDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("bdcentralmain.jdbc.pass")));
return dataSource;
}
#Bean
public PlatformTransactionManager bdCentralMainTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(bdCentralMainEntityManager().getObject());
return transactionManager;
}
}
DataSource 2
package com.smart4.configBases;
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import com.google.common.base.Preconditions;
#Configuration
#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(basePackages = {"com.smart4.bdcentral.repository.files"},
entityManagerFactoryRef = "bdCentralFilesEntityManager",
transactionManagerRef = "bdCentralFilesTransactionManager")
public class BdCentralFiles {
#Autowired
private Environment env;
public BdCentralFiles() {
super();
}
#Bean
public LocalContainerEntityManagerFactoryBean bdCentralFilesEntityManager() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(bdCentralFilesDataSource());
em.setPackagesToScan(new String[] { "com.smart4.bdcentral.domain.files" });
em.setPersistenceUnitName("bdcentralfiles");
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
em.setJpaVendorAdapter(vendorAdapter);
final HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("bdcentralfiles.hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("bdcentralfiles.hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Bean
public DataSource bdCentralFilesDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("bdcentralfiles.jdbc.pass")));
return dataSource;
}
#Bean
public PlatformTransactionManager bdCentralFilesTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(bdCentralFilesEntityManager().getObject());
return transactionManager;
}
}
not much to say with just the datasources, check the annotation configuration and make sure your objects are #Entity annotated. It doesn't sound like you actually want a "cross join", also you're looking at Hibernate, I kept reading Spring Boot JPA as spring "Data" JPA and was getting confused as to why it wasn't data jpa lol.

How to fix Error creating bean with name 'sessionFactory' error?

Trying to make some webapp with java? spring and hibernate. I am noob in java.
Nake all by the manual, but getting error
Error creating bean with name 'sessionFactory' defined in dev.test.config.HibernateConfig: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError
My HibernateConfig.Java
package dev.test.config;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#ComponentScan(basePackages = "dev.test")
#EnableTransactionManagement
#PropertySource(value = "classpath:/db.properties")
public class HibernateConfig {
private Environment environment;
#Autowired
public void setEnvironment(Environment environment) {
this.environment = environment;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
return properties;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("dev.test.models");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
}
In DAO file just add
#Autowired
private SessionFactory sessionFactory;
Before this changes? when i try to make app with temporary storage(just dict in app) all work.
Would be very glad for any help.

how do i resolve getCurrentSession() in mycode

i am beginner in java,spring&hibernate. when i using sessionFactory.getCurrentSession().saveOrUpdate(employee); igot error. but when i use sessionFactory.openSession().saveOrUpdate(employee); database insertion is possible. i want to use getCurrentSession() instead of open session .
mycode
myservice is
package com.simplecrud.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.simplecrud.dao.EmployeeDao;
import com.simplecrud.model.Employee;
#Service("employeeService")
#Transactional
public class EmployeeService {
#Autowired
EmployeeDao dao;
#Transactional
public String create(Employee employee)
{
System.out.println("service"+employee);
dao.create(employee);
return null;
}
}
my dao is
package com.simplecrud.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import com.simplecrud.model.Employee;
#Component
#Repository
public class EmployeeDao {
#Autowired
SessionFactory sessionFactory;
public void create(Employee employee){
sessionFactory.openSession().saveOrUpdate(employee);
/*sessionFactory.getCurrentSession().saveOrUpdate(employee);*/
/* protected Session getSession(){
return sessionFactory.getCurrentSession();
}*/
}
}
config file
package com.simplecrud.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration //Marks this class as configuration
//Specifies which package to scan
#ComponentScan("com.simplecrud")
//Enables Spring's annotations
#EnableWebMvc
public class Config {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/employee_db");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("mysql");
return driverManagerDataSource;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
// properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.c3p0.minPoolSize", "5");
properties.put("hibernate.c3p0.maxPoolSize", "10");
properties.put("hibernate.c3p0.idleTestPeriod", "300");
properties.put("hibernate.c3p0.timeout", "600");
properties.put("hibernate.c3p0.max_statement", "50");
properties.put("hibernate.c3p0.testConnectionOnCheckout", "false");
properties.setProperty("timeZone", "serverTimezone");
properties.put("hibernate.c3p0.preferredTestQuery", "select 1");
return properties;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addProperties(getHibernateProperties());
sessionBuilder.scanPackages("com.simplecrud.model");
//sessionBuilder.setInterceptor(new MySQLCalcFoundRowsInterceptor());
return sessionBuilder.buildSessionFactory();
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
}
help me anyone..

Hibernate, oauth2 could not obtain transaction-synchronized

I tried to make my own customDetailsService and when I tried to call server for token using http:
POST http://localhost:8080/SpringSecurityOAuth2Example/oauth/token?grant_type=password&username=bill&password=abc123
I got exception as a result:
<UnauthorizedException xmlns="">
<error>unauthorized</error>
<error_description>Could not obtain transaction-synchronized Session for current thread</error_description>
</UnauthorizedException>
What is more, when I debugged this I had determined that there is the problem with method userDaoImpl.findByLogin(login). But when I called it from my restController for test it worked and annotations were analogous.
#EnableTransactiomManagement is added in hibernate configuration and needed classes are annotated with #Transaction.
MyUserDetailsService
package com.maxim.spring.restcontroller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.maxim.spring.dao.UserDao;
import com.maxim.spring.model.User;
#Transactional
#Service("MyUserDetailsService")
public class MyUserDetailsService implements UserDetailsService {
#Autowired
#Qualifier("userDaoImpl")
private UserDao userDaoImpl;
#Transactional(readOnly=true)
#Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
User user = userDaoImpl.findByLogin(login);
if(user == null) {
System.out.println("User was not found ");
throw new UsernameNotFoundException(login);
} else {
System.out.println("Tu powinienem byc i jestem");
new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPass(), getUserRole(user));
}
return null;
}
public List<GrantedAuthority> getUserRole(User user) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_"+user.getRole()));
return authorities;
}
UserDaoImpl:
package com.maxim.spring.dao;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import com.maxim.spring.model.User;
#Transactional
#Repository("userDaoImpl")
public class UserDaoImpl extends AbstractDao implements UserDao{
public User findById(Integer id) {
#Override
public User findByLogin(String login) {
System.out.println("w srodku1");
Query qr = (Query) getSession().getCurrentSession().createQuery("from User u where u.login=:login").setParameter("login", login);
System.out.println("w srodku2");
User u = (User) qr.list().get(0);
System.out.println("w srodku3");
return u;
}
}
The hibernate configuration:
#EnableTransactionManagement
#Configuration
#ComponentScan({ "com.maxim.spring.configuration" })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.maxim.spring.model", "com.maxim.spring.services" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
How to make it work? What are my mistakes?
You are using getSession().getCurrentSession().......
if you put getSession().openSession().....It will works.
more info enter this discussion
Your #Transactional method loadUserByUsername() call #Transactional method findByLogin() that is conflict, can't open 2 transactions.
Idea for you:
Remove all #Transactional above class and add #Transactional on methods that you want to be transactional. Your method loadUserByUsername() must be transactional but your method findByLogin() can't be transactional because it is called from transactional method.

Categories

Resources