Soy nuevo en Spring y estaba intentando crear una aplicación web con la siguiente pila: Apache Tomcat 7, MySQL, Spring MVC, Hibernate 3 con anotaciones JPA.Spring + Hibernate con anotaciones: Ninguna sesión de Hibernate vinculada al thread
Estoy tratando de aprender siguiendo el libro "Primavera en acción, tercera edición" de Craig Walls.
Primero, quería crear una página que muestra algunas entradas que agregué manualmente a mi base de datos, pero parece que mi aplicación no es capaz de crear/recuperar ninguna sesión de Hibernate de mi SessionFactory. Aquí está mi raíz rastro causa pila:
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
com.nbarraille.www.dao.HibernateContactDAO.listContact(HibernateContactDAO.java:27)
com.nbarraille.www.controllers.HomeController.showHomePage(HomeController.java:24)
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:613)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Y aquí están mis clases interesadas/Los archivos de configuración:
Mi HibernateDAO:
@Repository
public class HibernateContactDAO implements ContactDAO {
private SessionFactory sessionFactory;
@Autowired
public HibernateContactDAO(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public void addContact(Contact contact) {
sessionFactory.getCurrentSession().save(contact);
}
public List<Contact> listContact() {
@SuppressWarnings("unchecked")
List<Contact> cl = sessionFactory.getCurrentSession().createQuery("from Contact").list();
return cl;
}
public void removeContact(Integer id) {
Contact contact = (Contact) sessionFactory.getCurrentSession().load(Contact.class, id);
if (null != contact) {
sessionFactory.getCurrentSession().delete(contact);
}
}
}
Mi clase de contacto:
@Entity
@Table(name="contacts")
public class Contact implements Serializable {
private static final long serialVersionUID = -5389913432051078273L;
@Id
@Column(name="id")
@GeneratedValue
private int id;
@Column(name="first_name")
private String firstname;
@Column(name="last_name")
private String lastname;
@Column(name="email")
private String email;
@Column(name="telephone")
private String telephone;
// Setters/Getters
}
Mi clase de controlador:
@Controller
public class HomeController {
private ContactDAO contactDAO; // I know I should pass through a service instead of accessing my DAO directly, and I usually do, but I skipped it here to simplify and try to locate the problem
@Inject
public HomeController(ContactDAO contactDAO){
this.contactDAO = contactDAO;
}
@RequestMapping({"/", "/home"})
public String showHomePage(Map<String,Object> model){
model.put("contacts", contactDAO.listContact());
return "index";
}
}
Aquí es mi Contexto archivo de datos de configuración:
<bean id="DBpropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/jdbc.properties" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/nbarraille" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.nbarraille.www.core" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Adds an advisor to any bean annotated with @Repository so that any platform-specific exception
are caught and then rethrown as one of Spring's unchecked data access exceptions -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
Aquí es mi config Dispatcher Servlet:
<mvc:resources mapping="/resources/**"
location="/resources/" />
<mvc:annotation-driven />
<context:component-scan base-package="com.nbarraille.www" />
<bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver" />
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles-def.xml</value>
</list>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
Y, por último, aquí está mi archivo web.xml:
<servlet>
<servlet-name>nbarraille</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>nbarraille</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/nbarraille-service.xml
/WEB-INF/nbarraille-data.xml
/WEB-INF/nbarraille-security.xml
</param-value>
</context-param>
Correcto. Quizás también considere usar la notación '@ Transactional' en su DAO como una alternativa a aop. –
Al agregar la cosa de filtro me liberé de ese error, gracias. ¿Qué es exactamente lo que está haciendo? No agregué el soporte de transacción aún, ya que no sé de qué se trata. – nbarraille
@nbarraille: ese filtro garantiza que su capa de visualización tenga acceso a la sesión de Hibernate. Tenga en cuenta que necesitará este filtro ** Y ** transacción configurada si desea que sus cosas funcionen correctamente. Tener este filtro no significa que tenga una transacción incluida en cada solicitud del usuario. Lea esto para obtener más información: http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html – limc