[英]Continuous server request causing issue of hibernate exception unsafe use of session
I have created Web application using - Spring 4.3, hibernate 5 and MySQL 5.6. 我已经使用Spring 4.3,Hibernate 5和MySQL 5.6创建了Web应用程序。
From Spring i am using - 1.Spring handler interceptor - for filtering each request. 从Spring我正在使用-1.Spring处理程序拦截器-过滤每个请求。
2.Spring MVC - To manage the REST web resource. 2.Spring MVC-管理REST Web资源。
3.Spring AOP - As Transaction manager with declarative approach(@Transactional) 3.Spring AOP-作为事务管理者,采用声明式方法(@Transactional)
4.Hibernate - ORM and session connection management. 4.Hibernate-ORM和会话连接管理。
Application is deployed successfully on server and i am able to login. 应用程序已成功部署在服务器上,并且我能够登录。
So now lets talk about my problem :- i logged into application and continuously hitting the request(using f5) after some time exception is thrown from hibernate DAO layer. 因此,现在让我谈谈我的问题:-我从休眠DAO层引发了一段时间异常后,登录到应用程序并连续命中该请求(使用f5)。
every time getting different exceptions like :- 每次遇到不同的异常,如:-
org.springframework.orm.hibernate5.HibernateSystemException: HHH000479: Collection [dao.domain.WebService.webServicePermissionMaps] was not processed by flush(). org.springframework.orm.hibernate5.HibernateSystemException:HHH000479:集合[dao.domain.WebService.webServicePermissionMaps]未被flush()处理。 This is likely due to unsafe use of the session (eg used in multiple threads concurrently, updates during entity lifecycle hooks).; 这可能是由于会话的不安全使用(例如,在多个线程中同时使用,在实体生命周期挂钩期间进行更新)。
Internal server error Found two representations of same collection: dao.domain.WebService.webServicePermissionMaps; 服务器内部错误找到相同集合的两个表示形式:dao.domain.WebService.webServicePermissionMaps;
3.${PATTERN}${PATTERN} java.lang.NullPointerException: null at org.hibernate.event.internal.AbstractFlushingEventListener.prepareCollectionFlushes(AbstractFlushingEventListener.java:178) ~[hibernate-core-5.2.7.Final.jar:5.2.7.Final] 3。$ {PATTERN} $ {PATTERN} java.lang.NullPointerException:在org.hibernate.event.internal.AbstractFlushingEventListener.prepareCollectionFlushes(AbstractFlushingEventListener.java:178)处为null〜[hibernate-core-5.2.7.Final.jar: 5.2.7。最终]
4.${PATTERN}${PATTERN} org.springframework.orm.hibernate5.HibernateSystemException: Found shared references to a collection: dao.domain.WebService.webServicePermissionMaps; 4。$ {PATTERN} $ {PATTERN} org.springframework.orm.hibernate5.HibernateSystemException:找到对集合的共享引用:dao.domain.WebService.webServicePermissionMaps; nested exception is org.hibernate.HibernateException: Found shared references to a collection: dao.domain.WebService.webServicePermissionMaps. 嵌套的异常是org.hibernate.HibernateException:找到对集合的共享引用:dao.domain.WebService.webServicePermissionMaps。
5.Caused by: java.sql.SQLException: No operations allowed after statement closed. 5.由:java.sql.SQLException:语句关闭后不允许执行任何操作。 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998) ~[mysql-connector-java-5.1.36.jar:5.1.36] 在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)〜[mysql-connector-java-5.1.36.jar:5.1.36]
Following is my code:- 以下是我的代码:
Spring configuration- 弹簧配置
@Configuration
@EnableWebMvc
@Import({DbConfiguration.class})
@ComponentScan(basePackages = "com")
@PropertySource("classpath:application.properties")
public class RestConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor()).excludePathPatterns("/security/authenticate").excludePathPatterns("/security/ssoAuthenticate");
registry.addInterceptor(authorizationInterceptor()).excludePathPatterns("/security/authenticate").excludePathPatterns("/security/ssoAuthenticate");
}
@Bean
public AuthorizationInterceptor authorizationInterceptor() {
return new AuthorizationInterceptor();
}
}
DB config class- 数据库配置类
@Configuration
@EnableTransactionManagement
public class DbConfiguration {
@Bean
public DataSource dataSource() throws NamingException {
return (DataSource) new JndiTemplate().lookup(env.getRequiredProperty("jdbc.url"));
}
@Bean
@Autowired
public LocalSessionFactoryBean sessionFactory() throws NamingException {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[]{"com.dao"});
sessionFactory.setHibernateProperties(hibProperties());
return sessionFactory;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager tm = new HibernateTransactionManager();
tm.setSessionFactory(sessionFactory);
return tm;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, "false");
return properties;
}
} }
Spring Interceptor- 弹簧拦截器
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
private static Logger log = LoggerFactory.getLogger(AuthenticationInterceptor.class);
@Autowired
private ApplicationContext appContext;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//variables declaration
try {
servicePath = (String ) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
WebServiceUtil webServiceUtil = (WebServiceUtil)appContext.getBean("webServiceUtil");
//This method causing hibernate erroe
boolean isAccessible = webServiceUtil.isWebServiceAccessbile(roles, servicePath, request.getMethod());
}catch (Exception e) {
log.error("Error occured in AuthorizationInterceptor.preHandle method role are : "+roles, e);
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.getWriter().write(e.getMessage());
return false;
}
return true;
}
} }
-Util Class(Want this class bean into request scope.This class dont have @Transactional) -Util Class(希望此类bean进入请求范围。此类没有@Transactional)
@Service("webServiceUtil")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "request")
public class WebServiceUtil {
@Autowired
private AuthorizationService authorizationService;
public boolean isWebServiceAccessbile(Set<String> roles, String basePath, String methodType)
throws SysException {
try {
List<WebService> webservices = authorizationService.getWebService(roles, methodType);
List<String> webserviceUrl = new ArrayList<String>();
for (WebService webService : webservices) {
webserviceUrl.add(webService.getUrl());
}
return webserviceUrl.contains(basePath);
} catch (SysException e) {
throw e;
}
}
}
-Service Class -服务等级
@Service("authorizationService")
public class AuthorizationServiceImpl implements AuthorizationService {
@Autowired
private WebServiceDAO webServiceDAO;
@Override
@Transactional
public List<WebService> getWebService(Set<String> roles, String method) throws DataAccessException {
return webServiceDAO.getWebServices(roles, method);
}
}
@Repository public class WebServiceDAOImpl extends BaseDAOImpl implements WebServiceDAO { @Repository公共类WebServiceDAOImpl扩展了BaseDAOImpl,实现了WebServiceDAO {
private static Logger log = LoggerFactory.getLogger(WebServiceDAOImpl.class);
@Override
public List<WebService> getWebServices(Set<String> roles, String methodType) throws DataAccessException {
TypedQuery<WebService> query = null;
try {
Session session = getSessionFromSessionFactory(getSessionFactory());
StringBuilder sqlString = new StringBuilder("select ws.* from WEB_SERVICE_PERMISSION_MAP wpm "+
"join WEB_SERVICE ws on ws.ID = wpm.WEB_SERVICE_ID "+
"join WEB_SERVICE_METHOD wsm on wsm.ID = wpm.WEB_SERVICE_METHOD_ID "+
"where wpm.PERMISSION_ID in "+
"(select pe.id from ROLE_PERMISSION rope "+
"inner join Permission pe on rope.PERMISSIONID = pe.id "+
"inner join Role ro on rope.ROLEID = ro.ID "+
"where ro.name in (:roles)) and "+
"wsm.NAME in (:method)");
query = session.createNativeQuery(sqlString.toString(), WebService.class);
query.setParameter("roles", roles);
query.setParameter("method", methodType);
} catch (Exception e) {
log.error("Error occured in WebServiceDAOImpl.getWebServices method while getting web services for roles : "+roles+" and request method type : "+methodType, e);
throw new DataAccessException("Error occured in WebServiceDAOImpl.getWebServices method while getting web services for roles : "+roles+" and request method type : "+methodType, e);
}
return query.getResultList();
}
} }
-Base DAO
public class BaseDAOImpl<T> implements BaseDAO<T> {
@Autowired
private SessionFactory sessionFactory;
private Session session;
private Class<T> domainClass;
public Session getSessionFromSessionFactory(SessionFactory sessionFactory) {
try {
session = sessionFactory.getCurrentSession();
} catch (HibernateException he) {
log.error("Error in getSessionFromSessionFactory :" + he.getStackTrace());
}
return session;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
}
Problem is resolved. 问题已解决。 It was my bad as i created session object at class level. 当我在类级别创建会话对象时,这很糟糕。 and session object is shared between threads. 并且会话对象在线程之间共享。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.