尝试使用我的@Service
带注释的类时,我收到以下异常:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at webapp.base.repository.GenericDaoImpl.saveOrUpdate(GenericDaoImpl.java:59) ~[base-0.0.1-SNAPSHOT-classes.jar:na]
at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:19) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:14) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.service.PageViewServiceImpl.savePageView(PageViewServiceImpl.java:26) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.interceptor.PageViewInterceptor.preHandle(PageViewInterceptor.java:29) ~[site-0.0.1-SNAPSHOT.jar:na]
at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api-3.0.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api-3.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:466) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:337) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:427) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:200) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote-7.0.52.jar:7.0.52]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote-7.0.52.jar:7.0.52]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) [tomcat-coyote-7.0.52.jar:7.0.52]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_65]
我初始化应用程序的方式很复杂,因此我需要提供完整基本代码的链接以获取其他信息:https://github.com/dtrunk90/webapp-base。 我正在使用它作为maven叠加。
这是必要的代码:
初始化程序(来自webapp-base):
public abstract class AbstractWebApplicationInitializer extends AbstractDispatcherServletInitializer {
@Override
protected String[] getServletMappings() {
return new String[] {"/*"};
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[] {encodingFilter};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
ConfigurableEnvironment environment = rootContext.getEnvironment();
environment.setDefaultProfiles("production");
PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles());
String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages");
rootContext.scan(basePackages);
return rootContext;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
return new AnnotationConfigWebApplicationContext();
}
}
初始化程序(来自我的webapp):
public class WebApplicationInitializer extends AbstractWebApplicationInitializer {
}
@Configuration
(来自webapp-base):
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
@Bean
public DataSource dataSource() throws IOException {
Properties conProps = PropertyUtil.getInstance().getProperties("jdbc");
if (conProps.containsKey("url")) {
DriverManagerDataSource dataSource = new DriverManagerDataSource(conProps.getProperty("url"), conProps);
dataSource.setDriverClassName(conProps.getProperty("driverClassName"));
return dataSource;
}
return null;
}
@Bean
public SessionFactory sessionFactory() throws IOException {
DataSource dataSource = dataSource();
if (dataSource != null) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages(PropertyUtil.getInstance().getPropertySplitTrimmed("hibernate", "packagesToScan"));
sessionBuilder.addProperties(PropertyUtil.getInstance().getProperties("hibernate"));
return sessionBuilder.buildSessionFactory();
}
return null;
}
@Bean
public HibernateTransactionManager transactionManager() throws IOException {
SessionFactory sessionFactory = sessionFactory();
if (sessionFactory == null) {
return null;
}
return new HibernateTransactionManager(sessionFactory);
}
}
@Configuration
(来自我的网络应用):
@Configuration
public class MainConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private PageViewInterceptor pageViewInterceptor; // Is annotated with @Component
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(pageViewInterceptor);
}
}
@Service
:
@Service
public class PageViewServiceImpl implements PageViewService {
@Autowired
private PageViewDao pageViewDao;
@Override
public void savePageView(long ip, String visitPage, String userAgent) {
PageView obj = new PageView();
obj.setVisitDate(new Date());
obj.setUserAgent(userAgent);
obj.setPage(visitPage);
obj.setIp(ip);
pageViewDao.saveOrUpdate(obj);
}
}
@Repository
:
@Repository
public class PageViewDaoImpl extends GenericDaoImpl<PageView, Long> implements PageViewDao {
@Override
public void saveOrUpdate(PageView obj) {
if (!obj.isBot()) {
super.saveOrUpdate(obj);
}
}
}
public abstract class GenericDaoImpl<T extends Identifier<I>, I extends Serializable> implements GenericDao<T, I> {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
if (sessionFactory == null) {
throw new IllegalStateException("SessionFactory has not been set on DAO before usage");
}
return sessionFactory;
}
@Transactional
public void saveOrUpdate(T obj) {
getSessionFactory().getCurrentSession().saveOrUpdate(obj);
}
}
然后我自动装配PageViewService
并使用其方法。
我知道这里有几个问题存在同样的问题,但我已经检查了一切:
Could not obtain transaction-synchronized Session for current thread
@EnableTransactionManagement
已提供HibernateException: Could not obtain transaction-synchronized Session for current thread
@Transactional
getSessionFactory().getCurrentSession()
Spring Hibernate - Could not obtain transaction-synchronized Session for current thread
@EnableTransactionManagement
已提供@Transactional
getSessionFactory().getCurrentSession()
答案 0 :(得分:7)
查看您的日志,我可以立即判断您的交易设置是否设置错误。这是因为您的堆栈跟踪中没有TransactionInterceptor
调用。
当您的Web控制器调用实际的Service方法时,您的Spring Service代理会调用TransactionInterceptor
。
确保使用Spring hibernate4类:
org.springframework.orm.hibernate4.HibernateTransactionManager
不要覆盖@Transactional
方法,而是使用模板模式。
请尝试使用JPATransactionManager
,以便您可以使用EntityManager
注释注入当前@PersistenceContext
。这比在每个DAO方法中调用sessionFactory.getCurrentSession()
要优雅得多。
答案 1 :(得分:3)
<强>一强>
您必须@Transactional
使用@Service
和@Repository
。它允许Spring通过Transaction支持应用和创建代理。
在您的代码中,@Service
类在课程级别或方法级别中没有@Transacional
<强>第二强>
实现WebApplicationInitializer
的类在哪里?
我看到你正在扩展课程..无论如何,我的观点是,以下是类似的地方:
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(CentralServerConfigurationEntryPoint.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(CentralWebConfigurationEntryPoint.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
CentralServerConfigurationEntryPoint.class
必须只扫描必须在服务器端工作的组件(@Service
,@Repository
,@Configuration
用于事务,Hibernate,DataSource等)
CentralWebConfigurationEntryPoint
必须只扫描必须在客户端/网络端工作的组件(@Controller
,@Configuration
用于格式化程序,磁贴,转换器等)
我不明白你的代码
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
ConfigurableEnvironment environment = rootContext.getEnvironment();
environment.setDefaultProfiles("production");
PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles());
String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages");
rootContext.scan(basePackages);
return rootContext;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
return new AnnotationConfigWebApplicationContext();
}
我的观点是:您必须在服务器和网络端有两个AnnotationConfigWebApplicationContext
。
答案 2 :(得分:0)
这个问题的答案非常简短,你只需要在你的dao类中使用@Transactional,将你的配置类标记为@EnableTransactionManagement并创建一个bean
**@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
return transactionManager;
}**
在这里,如果您看到EnableTransactionManagement注释中提供的代码示例,则建议使用DataSourceTransactionManager而不是HibernateTransactionManager。
答案 3 :(得分:0)
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory)
{
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setTransactionSynchronization(HibernateTransactionManager.SYNCHRONIZATION_ALWAYS);
htm.setDataSource(dataSource());
htm.setSessionFactory(sessionFactory);
return htm;
}
You just need to add
-------------------------------
htm.setTransactionSynchronization(HibernateTransactionManager.SYNCHRONIZATION_ALWAYS);
-------------------------------
I used dependencies
-----------------------------------
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.2.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>