Struts2和Hibernate5是怎样整合的
把 Struts2 和 Hibernate5 塞进同一个项目,和H合最省事的样整做法是让 Spring 当中间人。但很多老项目没上 Spring,和H合或者你只是样整想快速搭个 demo,那就得手动把这两个框架的和H合“线”接起来。核心就一件事:Struts2 的样整 Action 里要拿到 Hibernate 的 Session,并且这个 Session 得能跟着请求走,和H合不能开一个 Action 就 new 一个 SessionFactory。样整 我见过有人直接在 Action 的和H合 execute 方法里写 正经的接法是用一个 我习惯用拦截器。写一个 然后把 Action 里的 Session 获取改成 Struts2 的 Action 里拿 Session 还有个小坑。如果你在 Action 的成员变量上直接注入 Session,比如 实体类映射这块,Hibernate5 推荐用注解。 事务边界我放在拦截器里,Action 里只写业务逻辑和调 DAO。DAO 里用 还有一点,Struts2 的 最后说个实际调试经验。如果启动时报 SessionFactory sf = new Configuration().configure().buildSessionFactory();,然后 sf.openSession()。样整跑起来确实能存数据,和H合但每请求一次就重建一次 SessionFactory,样整连接池瞬间爆炸。和H合这跟整合没关系,样整这是和H合自杀。SessionFactory 只初始化一次,通常放在 ServletContextListener 或者静态工具类里。Hibernate5 的 Configuration 和 SessionFactory 都是线程安全的,Session 不是。所以你要么用 ThreadLocal 把 Session 绑到当前线程,要么用 Struts2 的拦截器在 Action 执行前开 Session,执行后关掉。HibernateSessionInterceptor,实现 com.opensymphony.xwork2.interceptor.Interceptor。在 intercept 方法里:Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = null; try { tx = session.beginTransaction(); ActionInvocation invocation = ...; String result = invocation.invoke(); tx.commit(); return result; } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); }HibernateUtil.getSessionFactory().getCurrentSession()。注意,getCurrentSession() 要求你在 hibernate.cfg.xml 里配 <property name="hibernate.current_session_context_class">thread</property>,否则它不知道往哪找当前 Session。配了 thread 之后,openSession() 和 getCurrentSession() 就是两套东西,别混用。private Session session; 然后指望拦截器给你 set 进去,那得写个 SessionAware 接口或者用 @Inject。但更直接的办法是在 execute 方法里调 HibernateUtil.getCurrentSession()。我偏向后者,少一层抽象,出问题好查。@Entity、@Table、@Id、@GeneratedValue 这些跟 Hibernate3/4 没区别。但要注意 @Transactional 别乱加,Struts2 的 Action 不是 Spring Bean 的时候,这个注解根本不生效。有人把 @Transactional 写在 Action 类上,跑起来报 No Session found for current thread,查半天以为是 Hibernate 配置错了,其实是注解没被处理。getCurrentSession() 拿 Session,不要自己开事务。比如一个 UserDao.save(User user),就两行:Session session = HibernateUtil.getCurrentSession(); session.save(user);。事务提交由拦截器统一管。这样 Action 里多个 DAO 调用能共享同一个事务,回滚也干净。struts.xml 里要注册这个拦截器,并放到默认栈里。别只写 <interceptor name="hibernateSession" class="..."/> 就完事,得在 <interceptor-stack name="myStack"> 里引用它,然后 <default-interceptor-ref name="myStack"/>。否则 Action 执行时拦截器根本不触发,Session 就是 null。Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment],八成是 hibernate.cfg.xml 里没配 hibernate.connection.driver_class 或者数据库 URL 写错了。跟 Struts2 没关系,是 Hibernate5 的 JDBC 环境初始化失败。先单独跑一个 main 方法测 Hibernate 能不能连上,再往 Struts2 里塞。
-
上一篇
-
下一篇