Nie można pozyskać Transakcji

Odpowiedz Nowy wątek
2015-07-13 14:32

Rejestracja: 7 lat temu

Ostatnio: 3 godziny temu

0

Witam, pisze mały projekt w SPring MVC i napotkałem pewien problem. Jak próbuje odczytać dane z bazy to dostaje na tomcacie

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:979)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
    org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
    com.benq.project.dao.daoimp.BrandDAOImp.readAll(BrandDAOImp.java:49)
    com.benq.project.controller.BrandController.showForm(BrandController.java:22)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:177)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
@Repository
public class BrandDAOImp implements GenericDAO<Brand,Long>
{
    @Autowired
   private SessionFactory sessionFactory;

   @Override   
   public void create(Brand brand)
   {    
     sessionFactory.getCurrentSession().save(brand);
   }

   @Override
   public void update(Brand brand)
   {
     sessionFactory.getCurrentSession().update(brand);
   }

    @Override
    public Brand read(Long id)
    {      
        return (Brand) sessionFactory.getCurrentSession().get(Brand.class, id);     
    }

    @Override
    public void delete(Brand brand) 
    {
        sessionFactory.getCurrentSession().delete(brand);
    }

    @Override
    @SuppressWarnings("unchecked")  
    public List<Brand> readAll()
    {
        Session session = sessionFactory.getCurrentSession();
        List<Brand> brands = session.createQuery("from Brand").list();

        return brands;
    }
}

```java
@Service
public class BrandServiceImp implements BrandService
{
    @Autowired
    private BrandDAOImp brandDAO;

    @Override
    @Transactional
    public void create(Brand entity)
    {
        brandDAO.create(entity);
    }

    @Override
    @Transactional
    public void update(Brand entity)
    {
        brandDAO.update(entity);        
    }

    @Override
    @Transactional
    public Brand read(Long id)
    {
        return brandDAO.read(id);
    }

    @Override
    @Transactional
    public void delete(Brand entity)
    {
        brandDAO.delete(entity);        
    }

    @Override
    @Transactional
    public List<Brand> readAll()
    {
        return brandDAO.readAll();
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <context:component-scan  base-package="com.benq.project.dao.daoimp" />
    <context:component-scan  base-package="com.benq.project.service.serviceimp" />
    <context:component-scan  base-package="com.benq.project.controller" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://192.168.56.2:5432/base" />
        <property name="username" value="postgres" />
        <property name="password" value="xxx" />
     </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <!-- >prop key="hibernate.hbm2ddl.auto">create</prop-->
      </props>
    </property>
    <property name="packagesToScan" value="com.benq.project.model" />
  </bean>

  <bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager" 
    p:sessionFactory-ref="sessionFactory">
  </bean>

  </beans>

Czy ktoś wie o co tutaj chodzi?

Pozostało 580 znaków

2015-07-13 14:38
Moderator

Rejestracja: 16 lat temu

Ostatnio: 5 godzin temu

A @Transactional na metodach z BrandDAOImp to gdzie ci wcięło? o_O BTW możesz całą klasę tak oznaczyć i nie musisz wtedy każdej metody z osobna. I uprzedzając, bo możliwe że tak zrobiłeś: Oznaczyć musisz IMPLEMENTACJE. @Transactional nie propaguje się z interfejsu.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
edytowany 2x, ostatnio: Shalom, 2015-07-13 14:39
Pokaż pozostałe 3 komentarze
Jakkolwiek serwis odpowiada za transakcję, to imho oprócz tego zawsze można zaanotować DAO jako @Transactional z propagacją na Required. Dzięki temu mamy pewność, że żadna metoda nie odpali go bez rozpoczęcia transakcji, a generalnie tego właśnie chcemy. - Dawid Kotarba 2015-12-10 22:29
@Dawid Kotarba absolutnie nie, bo w ten sposób "maskujesz" potencjalny poważny błąd wydajnościowy. Bo jak ktos nie zrobi transakcji wyżej a bedzie ciągnął z DAO to nie zobaczysz że cos jest nie tak póki nie zerkniesz w logi bazy albo aplikacja nie zacznie sie ślimaczyć. To trochę jak z oznaczaniem wszystkiego na Eager albo wszystko na Lazy i trzymanie otwartej sesji w widoku. Bardzo złe praktyki bo aplikacja jest zrypana ale w logach niby czysto ;] - Shalom 2015-12-10 23:03
@Shalom Dzięki za komentarz. Absolutnie się zgadzam i absolutnie nie o to mi chodziło. Mea culpa, miała być propagacja Mandatory, a nie Required (bo w sumie to po co ją explicite definiować), co zmieniło kontekst całej wypowiedzi. Tak, przy Required DAO zawsze odpali się transakcyjnie, nawet jeśli samo sobie jest inicjatorem transakcji. Przy mandatory, poleci wyjątek, gdy DAO nie będzie uczestnikiem już istniejącej transakcji, na przykład z serwisu. I o takim właśnie zabezpieczeniu mi chodzi. - Dawid Kotarba 2015-12-11 10:18
@Dawid Kotarba ale to trochę sztuka dla sztuki bo JPA/Hibernate i tak rzuci wyjątkiem jak spróbujesz czytać z bazy bez traksakcji ;) - Shalom 2015-12-11 10:30
@Shalom Ech ta moja nadgorliwość :P - Dawid Kotarba 2015-12-11 11:57

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0