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.
Related
I have strange behaviour of #Transactional annotation and EntityManager persist and merge methods. I've annotated method as #Transactional and in it I call EntityManager.persists(entity)...and nothing happens. Entity is not saved to DB, no exception fired, totally nothing. I've read tons of examples, SO questions, and my code seems ok but not working.
Hibernate config:
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jndi.JndiTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = {"com.mycompany"})
#DependsOn({"PropertiesConfig"})
public class HibernateConfig {
public HibernateConfig() {}
#Bean
public DataSource dataSource() throws NamingException {
return (DataSource) new JndiTemplate().lookup(PropertyService.getInstance().getProperty("jndi.jdbc.AGSQL"));
}
#Bean(name = "entityManager")
#DependsOn("dataSource")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
System.out.println("*** Init EntityManagerFactory ***");
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.mycompany" });
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean(name = "tm")
public PlatformTransactionManager transactionManager() throws NamingException {
System.out.println("*** Init TransactionManager ***");
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.dialect", PropertyService.getInstance().getProperty("hibernate.dialect"));
setProperty("show_sql", PropertyService.getInstance().getProperty("show_sql"));
setProperty("hibernate.connection.isolation", String.valueOf(Connection.TRANSACTION_READ_UNCOMMITTED));
}
};
}
}
Entity:
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
#Entity
#Table(name = "Vehicle", schema = "dbo")
public class VehicleEntity {
private Long deviceId;
private LocalDateTime dtEdit;
private String name;
#Id
#Column(name = "device_id")
public Long getDeviceId() {
return deviceId;
}
public void setDeviceId(Long deviceId) {
this.deviceId = deviceId;
}
#Basic
#Column(name = "dt_edit")
#UpdateTimestamp
public LocalDateTime getDtEdit() {
return dtEdit;
}
public void setDtEdit(LocalDateTime dtEdit) {
this.dtEdit = dtEdit;
}
#Basic
#Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Dao:
import com.mycompany.VehicleEntity;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Repository
public class VehicleDao {
#PersistenceContext(unitName = "entityManager")
private EntityManager entityManager;
protected EntityManager getEntityManager() {
return entityManager;
}
#Transactional(transactionManager = "tm")
public void persist(VehicleEntity entity) {
getEntityManager().persist(entity);
}
#Transactional("tm")
public void merge(VehicleEntity entity) {
getEntityManager().merge(entity);
}
}
And executing this code do totally nothing:
VehicleEntity ve = new VehicleEntity();
ve.setDeviceId(111L);
ve.setName("111");
vehicleDao.persist(ve);
I tried to check transaction status inside persist method:
((Session)this.getEntityManager().getDelegate()).getTransaction().getStatus() = NOT_ACTIVE
So I can conclude that transaction has not started, or started, but entitymanager did not see it automatically (see below). In one of the questions I saw that before calling persist(entity) entity manager was joined to the transaction and made the same thing:
#Transactional(transactionManager = "tm")
public void persist(T entity) {
getEntityManager().joinTransaction();
getEntityManager().persist(entity);
}
Aaaaand...it works. And transaction status become ACTIVE.
So my questions are:
- why it did not work without joinTransaction()? I've never seen it in examples...
- (possibly after solving 1st question this one will not make sense) persisting and merging actually are in abstract dao class, but I have many entities, many entities dao and many custom methods in them. And calling joinTransaction() in each of them is not good idea. How make it in pretty way?
EDIT:
Checked one more thing - added propagation property:
#Transactional(transactionManager = "tm", propagation = Propagation.MANDATORY)
public void persist(T entity) {
getEntityManager().persist(entity);
}
And it throws an exception:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
EDIT2:
Spring version 5.1.7.RELEASE
Hibernate version 5.4.10.Final
javax.persistence:javax.persistence-api:2.2 (dependency from hibernate-core)
Finally found the problem: I was migrating from SessionFactory to EntityManager and leave in config file old settings for SessionFactory. And the issue was that transaction managers has the same method names for SF and EM:
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(sessionFactory);
return transactionManager;
}
#Bean(name = "tm")
public PlatformTransactionManager transactionManager(#Qualifier("customEntityManager") EntityManagerFactory emf) {
System.out.println("*** Init TransactionManager ***");
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
This is mistake though bean names are different.
Changing SF transaction manager method to sessionTransactionManager(...) resolve the issue.
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.
I am trying to configure two EntityManagerFactory for one spring boot application. Each of those EntityManagerFactorys should work with different databases. Also would be great if one of them would be used as a default (e.g. when not explicit information was provided during on which one should be used).
Here is my code:
pkg/Application.java
package pkg;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
}
pkg/PrimaryDbConfig.java
package pkg;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
public class PrimaryDbConfig {
public static final String DB = "primary";
#Bean
#Primary
public DataSource primaryDataSource() {
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:file:~\\db\\test;AUTO_SERVER=TRUE");
ds.setUser("sa");
ds.setPassword("sa");
return ds;
}
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName(DB);
factoryBean.setDataSource(primaryDataSource());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("pkg.entities");
return factoryBean;
}
#Bean
#Primary
public PlatformTransactionManager primaryTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(primaryEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
pkg/SecondaryDbConfig.java
package pkg;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
public class SecondaryDbConfig {
public static final String DB = "secondary";
#Bean
public DataSource secondaryDataSource() {
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:file:~\\db\\test2;AUTO_SERVER=TRUE");
ds.setUser("sa");
ds.setPassword("sa");
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName(DB);
factoryBean.setDataSource(secondaryDataSource());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("pkg.entities");
return factoryBean;
}
#Bean
public PlatformTransactionManager secondaryTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(secondaryEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
pkg/repositories/PrimaryRepository.java
package pkg.repositories;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;
import javax.persistence.EntityManager;
#Repository
#Transactional
public class PrimaryRepository {
private final EntityManager entityManager;
public PrimaryRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public SomeEntity find(Integer id) {
return entityManager.find(SomeEntity.class, id);
}
}
pkg/repositories/SecondaryRepository.java
package pkg.repositories;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Repository
#Transactional("secondaryTransactionManager")
public class SecondaryRepository {
#PersistenceContext(unitName = "secondary")
private final EntityManager entityManager;
public SecondaryRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public SomeEntity find(Integer id) {
return entityManager.find(SomeEntity.class, id);
}
}
build.gradle
plugins {
id 'org.springframework.boot' version '1.5.7.RELEASE'
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile "com.h2database:h2:1.4.193"
compile "org.hibernate:hibernate-core:5.2.10.Final"
compile ("org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE") {
exclude module: 'tomcat-jdbc'
}
}
Running this app I am getting next error:
Description:
Parameter 0 of constructor in pkg.repositories.PrimaryRepository required a single bean, but 2 were found:
- org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
- org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
I am working with Spring 4.3.x and Hibernate 5.2.x. Since hibernate 5 JPA is standard way to user ORM with spring, I created a config to use Hibernate with JPA.
My spring configuration is,
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
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.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
#ComponentScan(basePackages = { "com.example.reports" })
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class SuperUserReportSpringConfiguration {
#Autowired
Environment environment;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendeorAdapter) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(jpaVendeorAdapter);
entityManagerFactory.setPackagesToScan("com.example.reports.domain");
entityManagerFactory.setPersistenceUnitName("onlineDB");
return entityManagerFactory;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(false);
adapter.setDatabasePlatform("org.hibernate.dialect.DB2400Dialect");
return adapter;
}
#Bean
DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setPoolName("hikariCP");
ds.setDriverClassName(this.environment.getProperty("jdbc.as400.db2.db.driver.classname"));
ds.setJdbcUrl(this.environment.getProperty("jdbc.as400.db2.db.url"));
ds.setUsername(this.environment.getProperty("jdbc.as400.db2.db.username"));
ds.setPassword(this.environment.getProperty("jdbc.as400.db2.db.password"));
ds.setMaximumPoolSize(10);
return ds;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager(emf);
return transactionManager;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
And I try to use #Transactional from javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional
In both the case, transaction manager is not working and I am getting error when trying to get child element from User entity,
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.reports.domain.User.userInetAddrs, could not initialize proxy - no Session
I am not sure if I am missing any configuration.
Hibernate entity,
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<UserInetAddr> userInetAddrs = new HashSet<UserInetAddr>(0);
Service class with #Transactional
User user = superUserReportDao.getUserSecurityRoles(id);
user.getUserInetAddrs().forEach(inetAddress -> {
});
And DAO Method with #Transactional
public User getUser(int userSeqId) {
return entityManager.find(User.class, userSeqId);
}
DAO Class transaction,
#Repository("superUserReportDao")
#Slf4j
#Transactional
public class SuperUserReportDaoImpl implements SuperUserReportDao {
#PersistenceContext(unitName="onlineDB")
private EntityManager onlineEntityManager;
And Service Class,
#Service("superUserReportService")
#Slf4j
public class SuperUserReportServiceImpl implements SuperUserReportService {
#Resource(name = "superUserReportDao")
private SuperUserReportDao superUserReportDao;
public void generateSuperUserReport() throws SQLException {
// -- generate Customer Super user report
generateSuperUserEmail(UserType.CUSTOMER);
}
#Transactional
private void generateSuperUserEmail(UserType userType) throws SQLException {
...
And my main class,
#Slf4j
#Component
public class SuperUserReportMain {
#Resource(name = "superUserReportService")
SuperUserReportService superUserReportService;
/**
* #param args
* #throws SQLException
*/
public static void main(String[] args) throws SQLException {
ApplicationContext context = new AnnotationConfigApplicationContext(SuperUserReportSpringConfiguration.class);
SuperUserReportMain reportMain = context.getBean(SuperUserReportMain.class);
reportMain.generateSuperUserReport();
((AnnotationConfigApplicationContext)context).close();
}
public void generateSuperUserReport() throws SQLException {
superUserReportService.generateSuperUserReport();
}
}
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..