Java SQLITE_错误SQL错误或缺少数据库(靠近“语句”:语法错误)

Java SQLITE_错误SQL错误或缺少数据库(靠近“语句”:语法错误),java,sqlite,intellij-idea,Java,Sqlite,Intellij Idea,我试图通过使用准备好的语句来应用注射攻击预防。我的代码的设置方式是,我有一个DBManager类,它通过存储负责执行sqlite语句的Java方法,充当Java和sqlite之间的催化剂。然后我有一些表类,它们存储sqlite语句本身。基本上,我想存储一个准备好的语句,该语句执行INSERT语句,并在调用open方法时与INSERT语句建立连接。下面是这两个类的摘录,我试图为IncomeStatementTable类中存储的常量创建一个准备好的语句: package com.anniemals.

我试图通过使用准备好的语句来应用注射攻击预防。我的代码的设置方式是,我有一个DBManager类,它通过存储负责执行sqlite语句的Java方法,充当Java和sqlite之间的催化剂。然后我有一些表类,它们存储sqlite语句本身。基本上,我想存储一个准备好的语句,该语句执行INSERT语句,并在调用open方法时与INSERT语句建立连接。下面是这两个类的摘录,我试图为IncomeStatementTable类中存储的常量创建一个准备好的语句:

package com.anniemals.database;

//the database package is meant to be the API package which
// takes all queried values from a database and sets them to values
// in each respective class

//MAKE SURE TO ADD METHODS TO ACCESS DB METADATA, FUNCTIONS, AND VIEWS LATER!
import com.anniemals.clients.ClientInfoIncomeStatement;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DBManager {

    public static final String DB_NAME = "clients.db";
    public static final String DB_PATH = "jdbc:sqlite:C:/Users/Steven/Documents/ProjectAnnieMalsRemote/Databases/" + DB_NAME;

    //SortOrders for queries
    public static final int ORDER_BY_NONE = 1;
    public static final int ORDER_BY_ASC = 2;
    public static final int ORDER_BY_DESC = 3;

    //Sets a connection to access and utilize sqlite expressions, which are assigned to the PreparedStatement variables for later use
    private Connection conn;

//Inserts
    private PreparedStatement insertIntoIncomeStatementPStatement;
//Composition has-a relationships for Table Classes
    private ClientInfoTable clientInfoTable;
    private IncomeStatementTable incomeStatementTable;

    public DBManager() {
        //Composition has-a relationships for Table Classes
        this.clientInfoTable = new ClientInfoTable();
        this.incomeStatementTable = new IncomeStatementTable();
    }

    public static DBManager getInstance() {
        return instance;
    }

    //Open and Close DB methods

    public boolean open(){
        try{
            conn = DriverManager.getConnection(DB_PATH);
//STATEMENT WHICH CAUSED THE ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            insertIntoIncomeStatementPStatement = conn.prepareStatement(incomeStatementTable.getInsertIncomeStatement());
            System.out.println("Database Opened");
            return true;
        } catch (SQLException e){
            System.out.println("Couldn't connect to database: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    public void close(){
        try {
            if (insertIntoIncomeStatementPStatement != null){
                insertIntoIncomeStatementPStatement.close();
            }
            if(insertIntoClientInfoPStatement != null){
                insertIntoClientInfoPStatement.close();
            }
            if (conn != null){
                conn.close();
                System.out.println("Database closed");
            }
        } catch (SQLException e){
            System.out.println("Couldn't close connection: " + e.getMessage());
        }
    }


public class IncomeStatementTable {

    //Column Labels
    public static final String TABLE_INCOME = "Income Statements";
    public static final String COLUMN_INCOME_ID = "_id";
    public static final String COLUMN_CLIENT_ID = "Client ID";
    public static final String COLUMN_INCOME_DATE = "Date";
    public static final String COLUMN_INCOME_TOTAL_OPER_EXPENSES = "Total Operating Expenses";
    public static final String COLUMN_INCOME_GROSS_PROFIT = "Gross Profit";
    public static final String COLUMN_INCOME_AMORTIZATION = "Amortization";
    public static final String COLUMN_INCOME_EBITDA = "E.B.I.T.D.A.";
    public static final String COLUMN_INCOME_PROFIT_BEFORE_TAX = "Profit Before Tax";
    public static final String COLUMN_INCOME_TAX = "Tax";
    public static final String COLUMN_INCOME_NET_PROFIT = "Net Profit";
    public static final String COLUMN_INCOME_EARN_PER_SHARE = "Earnings Per Share";

    //Column Indexes
    public static final int INDEX_INCOME_ID = 1;
    public static final int INDEX_INCOME_CLIENT_ID = 2;
    public static final int INDEX_INCOME_DATE = 3;
    public static final int INDEX_INCOME_TOTAL_OPER_EXPENSES = 4;
    public static final int INDEX_INCOME_GROSS_PROFIT = 5;
    public static final int INDEX_INCOME_AMORTIZATION = 6;
    public static final int INDEX_INCOME_EBITDA = 7;
    public static final int INDEX_INCOME_PROFIT_BEFORE_TAX = 8;
    public static final int INDEX_INCOME_TAX = 9;
    public static final int INDEX_INCOME_NET_PROFIT = 10;
    public static final int INDEX_INCOME_EARN_PER_SHARE = 11;

public static final String INSERT_INCOME_STATEMENT = "INSERT INTO " + TABLE_INCOME + "(" + COLUMN_INCOME_ID +
            ", " + COLUMN_CLIENT_ID +  ", " + COLUMN_INCOME_DATE  + ", " + COLUMN_INCOME_TOTAL_OPER_EXPENSES
            + ", " + COLUMN_INCOME_GROSS_PROFIT  + ", " + COLUMN_INCOME_AMORTIZATION  + ", " + COLUMN_INCOME_EBITDA
            + ", " + COLUMN_INCOME_PROFIT_BEFORE_TAX  + ", " + COLUMN_INCOME_TAX  + ", " + COLUMN_INCOME_NET_PROFIT
            + ", " + COLUMN_INCOME_EARN_PER_SHARE + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    public static String getInsertIncomeStatement() {
        return INSERT_INCOME_STATEMENT;
    }

我知道它与open方法中的变量赋值语句有关,因为当我注释掉它时,程序工作正常,我可以连接到数据库。我试着从其他问题中寻找与我在这里类似的答案,但是我对sqlite语句本身的语法所做的任何更改仍然会给我留下相同的错误。我已经尝试跟踪线程堆栈以查看错误中的语句引用了什么,但我仍然不确定。有人能帮我进一步指出问题所在吗

以下是跟踪堆栈:

org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (near "Statements": syntax error)
    at sqlite.jdbc@3.23.1/org.sqlite.core.DB.newSQLException(DB.java:909)
    at sqlite.jdbc@3.23.1/org.sqlite.core.DB.newSQLException(DB.java:921)
    at sqlite.jdbc@3.23.1/org.sqlite.core.DB.throwex(DB.java:886)
    at sqlite.jdbc@3.23.1/org.sqlite.core.NativeDB.prepare_utf8(Native Method)
    at sqlite.jdbc@3.23.1/org.sqlite.core.NativeDB.prepare(NativeDB.java:127)
    at sqlite.jdbc@3.23.1/org.sqlite.core.DB.prepare(DB.java:227)
    at sqlite.jdbc@3.23.1/org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:45)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:19)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:48)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:263)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:235)
    at sqlite.jdbc@3.23.1/org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:242)
    at AccountingFinancialModellingAndValuationApplication/com.anniemals.database.DBManager.open(DBManager.java:60)
    at AccountingFinancialModellingAndValuationApplication/com.anniemals.Main.main(Main.java:26)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)

提前感谢能够提供帮助的人。

此行定义的表名:

public static final String TABLE_INCOME = "Income Statements"
包含空格,这是不允许的。 更改为:

public static final String TABLE_INCOME = "[Income Statements]"
当表或列名包含空格时,必须将空格括在方括号或反勾中,ASCII代码096。 对于包含空格或点的列名,必须执行相同的操作:

奇怪的是,由于您试图向表中插入行,这意味着您已经创建了表。 但是怎么做呢?
CREATE语句中的表和列使用了什么名称?

我找到了解决问题的方法。这不是最漂亮的解决方案,但确实有效。基本上,我向DBManager类添加了一个create方法,正如forpas所建议的:

 public boolean checkCreateIncomeStatementTable(){
    String sql = "CREATE TABLE IF NOT EXISTS Income_Statements(\n" +
            " _id INTEGER PRIMARY KEY,\n" +
            " Client_ID INTEGER NOT NULL,\n" +
            " Date NUMERAL,\n" +
            " Total_Operating_Expenses DOUBLE NOT NULL,\n" +
            " Gross_Profit DOUBLE NOT NULL,\n" +
            " Amortization DOUBLE NOT NULL,\n" +
            " EBITDA DOUBLE NOT NULL,\n" +
            " Profit_Before_Tax DOUBLE NOT NULL,\n" +
            " Tax DOUBLE NOT NULL,\n" +
            " Net_Profit DOUBLE NOT NULL,\n" +
            " Earnings_Per_Share DOUBLE NOT NULL\n" +
            ");";
    try{
        conn = DriverManager.getConnection(DB_PATH);
        Statement statement = conn.createStatement();
        System.out.println("Database Opened");
        statement.executeQuery(sql);
        System.out.println("Checked creation of Income Statement Table");
        return true;
    } catch (SQLException e){
        System.out.println("Couldn't connect to database: " + e.getMessage());
        e.printStackTrace();
        return false;
    }
}
然后,对于每个包含空格的列标签,我使用下划线,因为主类出于某种原因不想读取括号

public static final String TABLE_INCOME = "Income_Statements";
public static final String COLUMN_INCOME_ID = "_id";
public static final String COLUMN_CLIENT_ID = "Client_ID";
public static final String COLUMN_INCOME_DATE = "Date";
public static final String COLUMN_INCOME_TOTAL_OPER_EXPENSES = "Total_Operating_Expenses";
public static final String COLUMN_INCOME_GROSS_PROFIT = "Gross_Profit";
public static final String COLUMN_INCOME_AMORTIZATION = "Amortization";
public static final String COLUMN_INCOME_EBITDA = "EBITDA";
public static final String COLUMN_INCOME_PROFIT_BEFORE_TAX = "Profit_Before_Tax";
public static final String COLUMN_INCOME_TAX = "Tax";
public static final String COLUMN_INCOME_NET_PROFIT = "Net_Profit";
public static final String COLUMN_INCOME_EARN_PER_SHARE = "Earnings_Per_Share";

现在一切似乎都正常了

我正在使用一个名为DB Browser for Sqlite的应用程序为我创建表。然而,当我在应用程序中检查数据库时,甚至没有创建表。我创建了这个表,并将所有带空格的值放在括号中,就像您所说的,但是我仍然得到相同的错误。我的java项目中没有CREATE语句。我是否仍然需要CREATE语句来检查表是否是通过if语句创建的?这是什么,android应用程序?您是否在Sqlite的DB Browser中创建了表?这是我尝试使用JavaFX和JDBC创建的桌面应用程序
public static final String TABLE_INCOME = "Income_Statements";
public static final String COLUMN_INCOME_ID = "_id";
public static final String COLUMN_CLIENT_ID = "Client_ID";
public static final String COLUMN_INCOME_DATE = "Date";
public static final String COLUMN_INCOME_TOTAL_OPER_EXPENSES = "Total_Operating_Expenses";
public static final String COLUMN_INCOME_GROSS_PROFIT = "Gross_Profit";
public static final String COLUMN_INCOME_AMORTIZATION = "Amortization";
public static final String COLUMN_INCOME_EBITDA = "EBITDA";
public static final String COLUMN_INCOME_PROFIT_BEFORE_TAX = "Profit_Before_Tax";
public static final String COLUMN_INCOME_TAX = "Tax";
public static final String COLUMN_INCOME_NET_PROFIT = "Net_Profit";
public static final String COLUMN_INCOME_EARN_PER_SHARE = "Earnings_Per_Share";