_@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
を自動配線して、そのメソッドを使用します。
ここで同じ問題に関するいくつかの質問があることは知っていますが、すでに何かを確認しました。
現在のスレッドのトランザクション同期セッションを取得できませんでした
@EnableTransactionManagement
_が提供されますHibernateException:現在のスレッドのトランザクション同期セッションを取得できませんでした
@Transactional
_を確認しましたgetSessionFactory().getCurrentSession()
Spring Hibernate-現在のスレッドのトランザクション同期セッションを取得できませんでした
@EnableTransactionManagement
_が提供されます@Transactional
_を確認しましたgetSessionFactory().getCurrentSession()
org.hibernate.HibernateException:現在のスレッドのトランザクション同期セッションを取得できませんでした
ログを見ると、トランザクション設定が誤って設定されていることがすぐにわかります。これは、スタックトレースにTransactionInterceptor
呼び出しがないためです。
TransactionInterceptor
は、Webコントローラーが実際のServiceメソッドを呼び出すときに、Spring Serviceプロキシによって呼び出されます。
Spring hibernate4クラスを使用していることを確認してください。
_org.springframework.orm.hibernate4.HibernateTransactionManager
_
_@Transactional
_メソッドをオーバーライドしないでください。代わりにテンプレートパターンを使用してください。
代わりにJPATransactionManager
を使用してみてください。代わりに、現在のEntityManager
に_@PersistenceContext
_アノテーションを挿入できます。これは、すべてのDAOメソッドでsessionFactory.getCurrentSession()
を呼び出すよりもはるかにエレガントです。
1つ
@Transactional
と@Service
には@Repository
を使用する必要があります。これにより、Springはトランザクションをサポートするプロキシを適用および作成できます。
あなたのコードでは、あなたの@Service
クラスは@Transacional
をクラスレベルでもメソッドレベルでも持っていません
2番目
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
は、トランザクション、休止状態、データソースなどの場合)
CentralWebConfigurationEntryPoint
は、クライアント/ Web側で機能する必要があるコンポーネントのみをスキャンする必要があります(@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();
}
私のポイントは次のとおりです。あなたmustサーバーとWebサイドに2つのAnnotationConfigWebApplicationContext
が必要です。
この質問IDに対する非常に短い回答です。@ Transactionalをdaoクラスで使用し、構成クラスを@EnableTransactionManagementとしてマークして、Beanを作成するだけです。
**@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
return transactionManager;
}**
ここで、EnableTransactionManagementアノテーションで使用可能なコード例が表示されている場合は、HibernateTransactionManagerの代わりにDataSourceTransactionManagerを使用することをお勧めします。