当 运行 来自 JSP 时,HSQLDB 不起作用,但当 运行 单独使用 Java 代码时,HSQLDB 不起作用
HSQLDB does not work when running from JSP, but works when running the Java code alone
我目前正在为自己的学习目的开发一个小项目,其中有一个数据库和一个 JSP 页面来访问该数据库。我的 Eclipse 上有一个 Java EE 项目,我正在使用以下项目:
- Tomcat 9
- HSQLDB
- Java JDK 15.0.1
- 日食
当 运行 下面的 Java 代码单独运行时,我得到了我想要的输出:
shop.RDB
package shop;
import java.sql.*;
import java.util.Collection;
import java.util.LinkedList;
public class RDB
{
private Connection con;
public static void main(String[] args)
{
try
{
RDB test = new RDB();
Collection<Product> ProductsInDB = test.getAllProducts();
for (Product p : ProductsInDB)
{
System.out.println(p.toString());
}
test.shutdown();
}
catch(SQLException e) {e.printStackTrace();}
}
public RDB()
{
try
{
Class.forName("org.hsqldb.jdbc.JDBCDriver");
con = DriverManager.getConnection("jdbc:hsqldb:file:shopDB;hsqldb.lock_file=false", "sa", "");
System.out.println("Created con");
}
catch (Exception e)
{
System.out.println("Exception: " + e);
}
}
public Collection<Product> getAllProducts()
{
return getProductCollection("Select * from Product");
}
public Collection<Product> getProductCollection(String query)
{
LinkedList<Product> list = new LinkedList<Product>();
try {
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(query);
while (rs.next())
{
Product product = new Product(
rs.getString("PID"),
rs.getString("name"),
rs.getDouble("price") );
list.add(product);
}
return list;
}
catch (Exception e)
{
System.out.println("Exception in getProducts(): " + e);
return null;
}
}
public void shutdown() throws SQLException
{
Statement st = con.createStatement();
// db writes out to files and performs clean shuts down
// otherwise there will be an unclean shutdown
// when program ends
st.execute("SHUTDOWN");
con.close(); // if there are no other open connection
}
}
但是,当我尝试做完全相同的事情并在 .jsp 文件中显示数据时,它不起作用:
ProductList.jsp
<%@ page contentType = "text/html;charset=UTF-8" language = "java" %>
<%@ page import = "shop.Product, shop.RDB, java.sql.*, java.util.Collection" %>
<html>
<head> <title>Amazonius Shop</title> </head>
<body>
<h3>Using Database</h3>
<table>
<tr style = "color: red">
<th> ID </th> <th> Product </th> <th> Price </th>
</tr>
<%
try {
RDB DB = new RDB();
Collection<Product> ProductsInDB = DB.getAllProducts();
for (Product p : ProductsInDB)
{
%>
<tr style = "color: blue">
<td> <%= p.PID %> </td>
<td> <%= p.name %> </td>
<td> <%= p.price %> </td>
</tr>
<% }
DB.shutdown();
}
catch(SQLException e) {e.printStackTrace();}
%>
</table>
</body>
</html>
- shop 是 Java 资源文件夹中的包
- 产品是自定义数据结构。
- ProductList 是 WebContent 文件夹中的 JSP 文件
并给出这个错误:
Mar 15, 2021 10:22:36 AM org.hsqldb.persist.Logger logInfoEvent
INFO: Database closed
Exception: java.sql.SQLException: file input/output error: shopDB.log
Mar 15, 2021 10:22:36 AM org.hsqldb.persist.Logger logSevereEvent
SEVERE: could not reopen database
org.hsqldb.HsqlException: file input/output error: shopDB.log
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.persist.Log.openLog(Unknown Source)
at org.hsqldb.persist.Log.open(Unknown Source)
at org.hsqldb.persist.Logger.open(Unknown Source)
at org.hsqldb.Database.reopen(Unknown Source)
at org.hsqldb.Database.open(Unknown Source)
at org.hsqldb.DatabaseManager.getDatabase(Unknown Source)
at org.hsqldb.DatabaseManager.newSession(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCDriver.getConnection(Unknown Source)
at org.hsqldb.jdbc.JDBCDriver.connect(Unknown Source)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
at shop.RDB.<init>(RDB.java:32)
at org.apache.jsp.lab6web.ProductList_jsp._jspService(ProductList_jsp.java:183)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:467)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:378)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:326)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
Exception in getProducts(): java.lang.NullPointerException: Cannot invoke "java.sql.Connection.createStatement()" because "this.con" is null
Mar 15, 2021 10:22:36 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [jsp] in context with path [/Education_Tests_Project] threw exception [An exception occurred processing [lab6web/ProductList.jsp] at line [50]
47: RDB DB = new RDB();
48: Collection<Product> ProductsInDB = DB.getAllProducts();
49:
50: for (Product p : ProductsInDB)
51: {
52: %>
53: <tr style = "color: blue">
Stacktrace:] with root cause
java.lang.NullPointerException: Cannot invoke "java.util.Collection.iterator()" because "ProductsInDB" is null
at org.apache.jsp.lab6web.ProductList_jsp._jspService(ProductList_jsp.java:186)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:467)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:378)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:326)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
服务器对其他类型的 JSP 代码工作正常。此外,我的 hsqldb.jar 在 Tomcat 的 lib 文件夹中(从教程中看到),Tomcat 在 Java 构建路径中。我已经尝试了几种方法;
- 将 .jar 文件放入 Java 构建路径
- 将 .jar 分别并同时放入 Java bin 和 lib 文件夹中
- 将.jar放入WEB-INF lib文件夹(从网站上看到的)
而且每次尝试都会出现同样的错误。
附加信息
shop.Product
package shop;
public class Product
{
public String PID;
public String name;
public double price;
public Product(String PID, String name, double price)
{
this.PID = PID;
this.name = name;
this.price = price;
}
public String toString()
{
return name + "\t " + price;
}
}
Java 构建路径
您的连接 URL 是问题所在。在 Tomcat 或其他应用服务器上,目录通常是只读的,您不能在那里创建数据库。请参阅 http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_variables_url 了解如何指向您的主目录或在 Tomcat 属性中定义为数据目录的目录。您不应在 URL 上使用 hsqldb.lock_file=false
,因为不建议将其用于正常使用。下面的示例使用主目录作为数据库位置。
con = DriverManager.getConnection("jdbc:hsqldb:file:~/shopDB", "sa", "");
我目前正在为自己的学习目的开发一个小项目,其中有一个数据库和一个 JSP 页面来访问该数据库。我的 Eclipse 上有一个 Java EE 项目,我正在使用以下项目:
- Tomcat 9
- HSQLDB
- Java JDK 15.0.1
- 日食
当 运行 下面的 Java 代码单独运行时,我得到了我想要的输出:
shop.RDB
package shop;
import java.sql.*;
import java.util.Collection;
import java.util.LinkedList;
public class RDB
{
private Connection con;
public static void main(String[] args)
{
try
{
RDB test = new RDB();
Collection<Product> ProductsInDB = test.getAllProducts();
for (Product p : ProductsInDB)
{
System.out.println(p.toString());
}
test.shutdown();
}
catch(SQLException e) {e.printStackTrace();}
}
public RDB()
{
try
{
Class.forName("org.hsqldb.jdbc.JDBCDriver");
con = DriverManager.getConnection("jdbc:hsqldb:file:shopDB;hsqldb.lock_file=false", "sa", "");
System.out.println("Created con");
}
catch (Exception e)
{
System.out.println("Exception: " + e);
}
}
public Collection<Product> getAllProducts()
{
return getProductCollection("Select * from Product");
}
public Collection<Product> getProductCollection(String query)
{
LinkedList<Product> list = new LinkedList<Product>();
try {
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(query);
while (rs.next())
{
Product product = new Product(
rs.getString("PID"),
rs.getString("name"),
rs.getDouble("price") );
list.add(product);
}
return list;
}
catch (Exception e)
{
System.out.println("Exception in getProducts(): " + e);
return null;
}
}
public void shutdown() throws SQLException
{
Statement st = con.createStatement();
// db writes out to files and performs clean shuts down
// otherwise there will be an unclean shutdown
// when program ends
st.execute("SHUTDOWN");
con.close(); // if there are no other open connection
}
}
但是,当我尝试做完全相同的事情并在 .jsp 文件中显示数据时,它不起作用:
ProductList.jsp
<%@ page contentType = "text/html;charset=UTF-8" language = "java" %>
<%@ page import = "shop.Product, shop.RDB, java.sql.*, java.util.Collection" %>
<html>
<head> <title>Amazonius Shop</title> </head>
<body>
<h3>Using Database</h3>
<table>
<tr style = "color: red">
<th> ID </th> <th> Product </th> <th> Price </th>
</tr>
<%
try {
RDB DB = new RDB();
Collection<Product> ProductsInDB = DB.getAllProducts();
for (Product p : ProductsInDB)
{
%>
<tr style = "color: blue">
<td> <%= p.PID %> </td>
<td> <%= p.name %> </td>
<td> <%= p.price %> </td>
</tr>
<% }
DB.shutdown();
}
catch(SQLException e) {e.printStackTrace();}
%>
</table>
</body>
</html>
- shop 是 Java 资源文件夹中的包
- 产品是自定义数据结构。
- ProductList 是 WebContent 文件夹中的 JSP 文件
并给出这个错误:
Mar 15, 2021 10:22:36 AM org.hsqldb.persist.Logger logInfoEvent
INFO: Database closed
Exception: java.sql.SQLException: file input/output error: shopDB.log
Mar 15, 2021 10:22:36 AM org.hsqldb.persist.Logger logSevereEvent
SEVERE: could not reopen database
org.hsqldb.HsqlException: file input/output error: shopDB.log
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.persist.Log.openLog(Unknown Source)
at org.hsqldb.persist.Log.open(Unknown Source)
at org.hsqldb.persist.Logger.open(Unknown Source)
at org.hsqldb.Database.reopen(Unknown Source)
at org.hsqldb.Database.open(Unknown Source)
at org.hsqldb.DatabaseManager.getDatabase(Unknown Source)
at org.hsqldb.DatabaseManager.newSession(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCDriver.getConnection(Unknown Source)
at org.hsqldb.jdbc.JDBCDriver.connect(Unknown Source)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
at shop.RDB.<init>(RDB.java:32)
at org.apache.jsp.lab6web.ProductList_jsp._jspService(ProductList_jsp.java:183)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:467)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:378)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:326)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
Exception in getProducts(): java.lang.NullPointerException: Cannot invoke "java.sql.Connection.createStatement()" because "this.con" is null
Mar 15, 2021 10:22:36 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [jsp] in context with path [/Education_Tests_Project] threw exception [An exception occurred processing [lab6web/ProductList.jsp] at line [50]
47: RDB DB = new RDB();
48: Collection<Product> ProductsInDB = DB.getAllProducts();
49:
50: for (Product p : ProductsInDB)
51: {
52: %>
53: <tr style = "color: blue">
Stacktrace:] with root cause
java.lang.NullPointerException: Cannot invoke "java.util.Collection.iterator()" because "ProductsInDB" is null
at org.apache.jsp.lab6web.ProductList_jsp._jspService(ProductList_jsp.java:186)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:467)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:378)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:326)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
服务器对其他类型的 JSP 代码工作正常。此外,我的 hsqldb.jar 在 Tomcat 的 lib 文件夹中(从教程中看到),Tomcat 在 Java 构建路径中。我已经尝试了几种方法;
- 将 .jar 文件放入 Java 构建路径
- 将 .jar 分别并同时放入 Java bin 和 lib 文件夹中
- 将.jar放入WEB-INF lib文件夹(从网站上看到的)
而且每次尝试都会出现同样的错误。
附加信息
shop.Product
package shop;
public class Product
{
public String PID;
public String name;
public double price;
public Product(String PID, String name, double price)
{
this.PID = PID;
this.name = name;
this.price = price;
}
public String toString()
{
return name + "\t " + price;
}
}
Java 构建路径
您的连接 URL 是问题所在。在 Tomcat 或其他应用服务器上,目录通常是只读的,您不能在那里创建数据库。请参阅 http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_variables_url 了解如何指向您的主目录或在 Tomcat 属性中定义为数据目录的目录。您不应在 URL 上使用 hsqldb.lock_file=false
,因为不建议将其用于正常使用。下面的示例使用主目录作为数据库位置。
con = DriverManager.getConnection("jdbc:hsqldb:file:~/shopDB", "sa", "");