提交表单时Struts 2 Hibernate空指针异常

Posted

技术标签:

【中文标题】提交表单时Struts 2 Hibernate空指针异常【英文标题】:Struts 2 Hibernate null pointer exception while submitting the form 【发布时间】:2013-09-08 08:17:54 【问题描述】:

我正在尝试通过集成 Struts 2 和 Hibernate 创建一个注册页面。但是当我运行下面的代码时,当我点击注册按钮时,我得到一个空指针异常。

休眠配置文件:

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.mysqlDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/db_socialnetwork</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">root</property>
    <mapping resource="hibernate.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

休眠映射文件:

<hibernate-mapping>
  <class name="models.User" table="tbl_user"> //DAO Class
        <meta attribute="class-description">
            This class contains a sample.
        </meta>
        <id column="user_id" name="id" type="int">
            <generator class="increment"/>
        </id>
        <property column="user_name" name="name" type="string"/>
        <property column="user_pwd" name="pwd" type="string"/>

        <property column="user_email" name="email" type="string"/>
        <property column="user_address" name="address" type="string"/>
        <property column="user_phno" name="phno" type="int"/>
    </class>
</hibernate-mapping>

struts.xml:

<struts>
    <!-- Configuration for the default package. -->
    <constant name="struts.devMode" value="true" />
    <package name="default" extends="struts-default" namespace="/">
        <action name="register" class="models.RegisterAction" method="execute">
            <result name="success">/home.jsp</result>
        </action>
    </package>
</struts>

web.xml:

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

HibernateUtil:

public class HibernateUtil 
private static final SessionFactory sessionFactory;

    static 
        try 
                  //new SchemaExport(config).create(true,true);

        sessionFactory = new Configuration().configure().buildSessionFactory();

         catch (Throwable ex) 
            // Log the exception.
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        
    

    public static SessionFactory getSessionFactory() 
        return sessionFactory;
    


注册表:

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <s:form action="register">
            <s:textfield name="name" label="Name"/>
            <s:textfield name="pwd" label="Password"/>

            <s:textfield name="email" label="Email"/>
            <s:textarea name="address" label="Address"/>
            <s:textfield name="phno" label="Mobile"/>

            <s:submit value="Register"/>
        </s:form>
    </body>
</html>

RegisterAction:

public class RegisterAction extends ActionSupport implements ModelDriven<User>
    User u = new User();
    UserDao udao = new UserDao();
    public RegisterAction() 
    

    public String execute() throws Exception 

        udao.addUser(u);
        return "success";
    

    @Override
    public User getModel() 
        throw new UnsupportedOperationException("Not supported yet.");
    

    public User getU() 
        return u;
    

    public void setU(User u) 
        this.u = u;
    
    

User类:

public class User 
        int id, phno;
    String name, pwd, email, address;

    public String getAddress() 
        return address;
    

    public void setAddress(String address) 
        this.address = address;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public int getPhno() 
        return phno;
    

    public void setPhno(int phno) 
        this.phno = phno;
    

    public String getPwd() 
        return pwd;
    

    public void setPwd(String pwd) 
        this.pwd = pwd;
    


UserDao:

class UserDao 


    public UserDao() 
    

    public static void addUser(User u) 

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction t = session.beginTransaction();
        int i = (Integer)session.save(u);
        t.commit();
        session.close();
    

数据库由以下字段组成:

id - 自动生成,int,主键 姓名, 密码, 电子邮件, 地址 - 字符串, phno - int

显示的错误是:

INFO: Hibernate 3.2.5
INFO: hibernate.properties not found
INFO: Bytecode provider name : cglib
INFO: using JDK 1.4 java.sql.Timestamp handling
INFO: configuring from resource: /hibernate.cfg.xml
INFO: Configuration resource: /hibernate.cfg.xml
INFO: Reading mappings from resource : hibernate.hbm.xml
SEVERE: Error parsing XML: XML InputStream(17) The content of element type "class" must match "(meta*,subselect?,cache?,synchronize*,comment?,tuplizer*,(id|composite-id),discriminator?,natural-id?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,((join*,subclass*)|joined-subclass*|union-subclass*),loader?,sql-insert?,sql-update?,sql-delete?,filter*,resultset*,(query|sql-query)*)".
SEVERE: Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate.hbm.xml
WARNING: StandardWrapperValve[default]: PWC1406: Servlet.service() for servlet default threw exception
org.xml.sax.SAXParseException: The content of element type "class" must match "(meta*,subselect?,cache?,synchronize*,comment?,tuplizer*,(id|composite-id),discriminator?,natural-id?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,((join*,subclass*)|joined-subclass*|union-subclass*),loader?,sql-insert?,sql-update?,sql-delete?,filter*,resultset*,(query|sql-query)*)".
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:387)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:321)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.handleEndElement(XMLDTDValidator.java:2020)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.endElement(XMLDTDValidator.java:904)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1750)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2906)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:624)
        at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:486)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:810)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:740)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:110)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:525)
        at org.dom4j.io.SAXReader.read(SAXReader.java:465)
        at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:499)
        at org.hibernate.cfg.Configuration.addResource(Configuration.java:566)
        at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1587)
        at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1555)
        at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1534)
        at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1508)
        at org.hibernate.cfg.Configuration.configure(Configuration.java:1428)
        at org.hibernate.cfg.Configuration.configure(Configuration.java:1414)
        at models.HibernateUtil.<clinit>(HibernateUtil.java:24)
        at models.RegisterAction.<init>(RegisterAction.java:10)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:539)
        at java.lang.Class.newInstance0(Class.java:372)
        at java.lang.Class.newInstance(Class.java:325)
        at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:119)
        at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:150)
        at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:139)
        at com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:109)
        at com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:288)
        at com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:388)
        at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:187)
        at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
        at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
        at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:47)
        at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:478)
        at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
        at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
        at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
        at java.lang.Thread.run(Thread.java:717) 

【问题讨论】:

【参考方案1】:

您误解了 DAO/DTO 模式。 DAO/DTO 不应该是静态的sessionFactory 通常每个应用程序只构建一次更好,因为这是一个耗时的过程。

更好地实现session per thread pattern。编写HibernateUtil 类来构建sessionFactory 并获取会话。

那么你的 DAO 会是这样的

public class UserDao 

    public Session getSession() 
      return HibernateUtil.getSession();
    

    public void closeSession() 
      HibernateUtil.closeSession();
    

    public void addUser(User u)     
        Session session = getSession();
        Transaction t = session.beginTransaction();
        int i = (Integer)session.save(u);
        t.commit();
        closeSession();
    

在你写的动作中

private UserDao userDao = new UserDao();

public String execute() throws Exception 
    User u = new User();
    u.setAddress(address);
    u.setEmail(email);
    u.setName(name);
    u.setPhno(phno);
    u.setPwd(pwd);
    userDao.addUser(u);
    return "success";

【讨论】:

错误现在是 org.hibernate.InvalidMappingException: 无法从资源 hibernate.hbm.xml 解析映射文档 罗马C:我试过了..它显示“org.xml.sax.SAXParseException:元素类型“类”的内容必须匹配“(元*,子选择?,缓存?,同步* ,comment?,tuplizer*,(id|composite-id),discriminator?,natural-id?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component |properties|any|map|set|list|bag|idbag|array|primitive-array)*,((join*,subclass*)|joined-subclass*|union-subclass*),loader?,sql-insert? ,sql-update?,sql-delete?,filter*,resultset*,(query|sql-query)*)".". 在 Hibernateutil 中,我已将 sessionfactory 、 session 对象和 getSession() & closeSession() 设为静态。除非我将这些设为静态,否则我无法在 userdao 中访问 getsession() 或 closesession .. 使用HibernateUtil 静态访问getSession() &amp; closeSession()。你读过这个答案吗?它没有向您展示如何访问会话吗?【参考方案2】:

RegisterAction 类中,您调用了静态方法UserDao.addUser(u)UserDao 类的 sf 字段仅在您调用 UserDao 的构造函数时才被初始化,但在您的情况下,构造函数永远不会被调用 => sf 永远不会被初始化,这就是为什么调用 sf.openSession(); 会抛出NullPointerException();

您应该在调用其方法之一之前初始化sf

请注意,在非静态和/或非同步方法中初始化静态字段是一种非常糟糕的做法。

【讨论】:

以上是关于提交表单时Struts 2 Hibernate空指针异常的主要内容,如果未能解决你的问题,请参考以下文章

struts2框架之重复提交问题

Struts2系列:(13)防表单重复提交(token + 拦截器)

关于Strutshibernatespring三大框架详解。

关于struts2防止表单重复提交

使用Struts 2防止表单重复提交

12-struts2防止表单重复提交