简体   繁体   中英

@Transactional not working with spring and hibernate (get is not valid without active transaction)

I've created a spring-mvc application. the configurations look like below:

dispatcher-servlet.xml

<beans >
   <mvc:annotation-driven />
   <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

   <context:component-scan base-package="my.server.controller" />

</beans>

applicationContext.xml

<beans >
     <context:annotation-config />
     <tx:annotation-driven transaction-manager="transactionManager"/>
     <context:component-scan base-package="my.server.dao" />
     <context:component-scan base-package="my.server.service" />


    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="org.postgresql.Driver" />
      <property name="url" value="jdbc:postgresql://localhost:5432/jahanserver" />
      <property name="username" value="postgres" />
      <property name="password" value="postgres" />
    </bean>

   <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="annotatedClasses">
        <list>
            <value>my.server.entity.TreeItem</value>
            <value>my.server.entity.TreeItemDetail</value>
            <value>my.server.entity.LayerItem</value>
        </list>
      </property>
      <property name="hibernateProperties">
        <props>
           <prop key="hibernate.dialect">org.hibernate.spatial.dialect.postgis.PostgisDialect</prop>
            <prop key="hibernate.current_session_context_class">thread</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
            <prop key="hibernate.connection.charSet">UTF-8</prop>
            <prop key="hibernate.default_schema">public</prop>
        </props>
      </property>
   </bean>
   <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory"/>
   </bean>
</beans>

applicationContext.xml is loaded by the following lines in the web.xml :

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/security.xml</param-value>
</context-param>

my.server.service.TreeServiceImpl

@Service
public class TreeServiceImpl implements TreeService {

   @Inject
   TreeDao treeDao;

   @Override
   @Transactional
   public TreeItem getTreeItem(Long id) {
       return treeDao.getTreeItem(id);
   }
}

my.server.dao.TreeDaoImpl

@Service
@Singleton
public class TreeDaoImpl extends AbstractDaoImpl implements TreeDao{

    public TreeItem getTreeItem(Long id){
        return (TreeItem)sessionFactory.getCurrentSession().get(TreeItem.class, id);
    }

    ...
}

my.server.controller.TreePermissionController.java

@RestController
@RequestMapping("/treePermission")
public class TreePermissionController implements InitializingBean{

   @Inject 
   TreeService treeService;

   private final PermissionFactory permissionFactory = new DefaultPermissionFactory();

   @Override
   public void afterPropertiesSet() throws Exception {
      Assert.notNull(treeService, "HBUtil cannot be null");
   }

   @RequestMapping(method = RequestMethod.GET, value = "/addPermission")
   public TreeItem addPermission(HttpServletRequest request, 
        @RequestParam Long id ) throws IOException {
       TreeItem item = treeService.getTreeItem(id);

       PrincipalSid sid = new PrincipalSid("dariush");
       Permission permission = permissionFactory.buildFromMask(16);

       try {
           treeService.addPermission(item, sid, permission);
       } catch (DataAccessException existingPermission) {
           existingPermission.printStackTrace();

       }
       return item;
   }

}

In the controller I call this:

TreeItem item = treeService.getTreeItem(id);

And I face this error:

org.hibernate.HibernateException: get is not valid without active transaction

Some questions with the same problem have been asked. I followed all of the suggestions but it's still a problem for me. How can I solve it? please help!

When using spring and spring managed transactions never use hibernate.current_session_context_class property unless you are using JTA.

Actually Spring will by default set its own CurrentSessionContext implementation (the SpringSessionContext), however if you set it yourself this will not be the case means it's breaking proper transaction integration.

so please remove/Comment-Out below line of hibernateProperties in applicationContext.xml

<prop key="hibernate.show_sql">true</prop>

Hope this should resolve your error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM