没有Hibernate Session绑定到线程,并且配置不允许在不使用@contoller的情况下创建非事务性的

时间:2014-03-01 06:51:16

标签: java spring hibernate

我是spring framework的新手。我已经集成了spring + hibernate来创建RESTFUI API Web服务。

public interface IGenericDao {
 long persists(T clazz) throws ResourceFailureException;
 List select(T clazz)throws ResourceFailureException;
}

@Repository(value="genericDao")
public class GenericDao  implements IGenericDao {

 @Autowired
 SessionFactory sessionFactory;

 @Override
 public long persists(T clazz) throws ResourceFailureException {
  long generatedID;
  generatedID = (Long) getCurrentSession().save(clazz);
  getCurrentSession().getTransaction().commit();
  return generatedID;
 }

 @Override
 public List select(T clazz) throws ResourceFailureException {
  String queryStr = " FROM "+clazz.getClass().getName()+" as table WHERE (table.isDelete is null OR"
    + " table.isDelete = false) ";
  return this.select(queryStr);
 }

 protected final Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
}

//实施GenericDAO类

@Repository(value="roleCapabilityDao")
public class RoleCapabilityDAO extends GenericDao{

 public final void persistRole(final Role role) throws ResourceFailureException {
  persists(role);
 }

 public final List getRoles(final String whereString)
   throws ResourceFailureException {
  String queryStr = "FROM Role " + whereString;
  return select(queryStr);
 }

 public final Role getRoleById(final int roleId) throws ResourceFailureException {
  String whereString = "WHERE id=" + roleId;
  List roles = getRoles(whereString);
  if (roles != null && !roles.isEmpty()) {
   return roles.get(0);
  }
  return null;
 }
}

// Servlet-context类。

@Transactional
public class HibernateUtility {

 private static Logger logger =Logger.getLogger(HibernateUtility.class.getName());

 public HibernateUtility() {


 }

 @Autowired(required=true)
 RoleCapabilityDAO roleCapabilityDao;

 @Autowired(required=true)
 UserDAO userDao;


 public void createDefaultUser(final ServletContext context) {

  SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, context);

  Users user = new Users();
  Role role = new Role();
  .....

  try {
   role = roleCapabilityDao.getRoleByName("SystemAdmin");
  }catch (ResourceFailureException re) {
   logger.error("Resource not found" +re.getMessage());
  } 
}

的applicationContext.xml

<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config />
<context:component-scan base-package="com.base" use-default-filters="false"/>

<bean id="propertyConfigurer"
    .....
</bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}">
    <property name="testOnBorrow" value="true"/>
    </bean>

 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
     <property name="configurationClass">
         <value>org.hibernate.cfg.AnnotationConfiguration</value>
     </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
  </bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"></property>
</bean>

的web.xml

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

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<servlet>
    <servlet-name>HibernateUtility</servlet-name>
    <servlet-class>com.base.hibernate.HibernateUtilityServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

// RESTFUL API调用

@Path("/roles")
@Service
@Transactional
public class RoleCapabilityResource {

    public RoleCapabilityResource(){
        super();
    }

    @Autowired
    UserDAO userDao;

    @Autowired
    RoleCapabilityDAO roleCapabilityDao;

    private static Logger roleLogger=Logger.getLogger(RoleCapabilityResource.class.getName());

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/getAllRoles")
    @Loggable(value = LogLevel.DEBUG)
    @CapabilityCode(value = "C_User_R")
    public Response getAllRoles(@Context final HttpServletRequest request) {

        HttpSession session = request.getSession();
        try {
        String loggedUser = session.getAttribute("userName").toString();
        Users user = userDao.getCurrentUser(loggedUser.trim());
        if(user == null){
            return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity("Current User not found").build();
        }
        List<Role> roleList = roleCapabilityDao.getValidRolesForUserRole(user.getRole().getName(), false);
        JSONObject allRolesJson = getRoleJSON(roleList);
        return Response.status(Response.Status.OK).type(MediaType.APPLICATION_JSON).entity(allRolesJson).build();
    } catch (ResourceFailureException re) {
            roleLogger.error("Error in resource"+re.getMessage());
            return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity(re.toString()).build();
        } 
    }
}

// HibernateUtilizyServlet

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * Hibernate Utility Servlet is invoked only once during JBoss Startup.
 */
@Service
@Transactional
public class HibernateUtilityServlet extends HttpServlet {



    /**
     * Default serial Version ID.
     */
    private static final long serialVersionUID = 1L;


    @Override
     public void init(ServletConfig config) {
            try {
                super.init(config);
                ServletContext context = getServletContext();
                HibernateUtility hibernateUtil = new HibernateUtility();
                hibernateUtil.createDefaultUser(context);
            } catch (ServletException e) {
                e.printStackTrace();
            }

     }

}

如果我运行应用程序,则会抛出以下错误消息

StandardWrapper.Throwable: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
 at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) [:3.1.0.RELEASE]
 at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685) [:3.6.0.Final]
 at com.base.dao.GenericDao.getCurrentSession(GenericDao.java:186) [:]
 at com.base.dao.GenericDao.select(GenericDao.java:80) [:]
 at com.base.dao.RoleCapabilityDAO.getRoles(RoleCapabilityDAO.java:29) [:]
 at com.base.dao.RoleCapabilityDAO.getRoleByName(RoleCapabilityDAO.java:40) [:]
 at com.base.hibernate.HibernateUtility.createDefaultUser(HibernateUtility.java:180) [:]
 at com.base.hibernate.HibernateUtilityServlet.init(HibernateUtilityServlet.java:41) [:]

我尝试过如下所述的链接,

1。Spring MVC + Hibernate: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here。 2。I am receiving HibernateException "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"

但我还没有解决。唯一的区别是我没有使用@controller注释。

如何解决此错误? 如何通过spring设置会话句柄?

1 个答案:

答案 0 :(得分:0)

HibernateUtilityServlet不是Spring Bean!它只是由Servlet容器(而不是Spring)创建的一些简单的Http Servlet。

因此

  • HibernateUtilityServlet处的Spring注释将被忽略(如果您的Object是Spring Bean(由Spring创建),则仅考虑它们)
  • 你不能在HibernateUtilityServlet
  • 中注入一些东西

Futuremore:当你用new创建一个实例时(就像你HibernateUtility hibernateUtil = new HibernateUtility();一样),那么这个对象将不是Spring Bean。因此 (你已经知道了):

  • 此类中的Spring注释将被忽略
  • 你不能在这个对象中注入一些东西

我真的不知道你想用这个HibernateUtilityServlet做什么,但看起来你试图在应用程序启动时设置数据库。 - 更简单的方法是使用弹簧默认功能:

@Component
public class OnStartupAction implements ApplicationListener<ContextStartedEvent> {

  @Override
  public void onApplicationEvent(final ContextStartedEvent event) {
    // do whatever you need here 
  }
}

我的answer中的更多细节。