如何在H2中定义Oracle打包过程以进行测试

时间:2019-07-16 17:15:08

标签: oracle spring-boot testing plsql h2

我正在测试一个将数据读/写到Oracle DB的Spring Boot应用程序。该Oracle DB具有Oracle软件包以及这些软件包中的过程。在某个时候,spring boot应用程序通过实体存储库调用此过程,如下所示:

@Repository
public interface StudentRepository extends JpaRepository<Student, String> {

@Modifying
@Query(value = "begin sch1.STUDENT_PACKAGE.Set_Grades_To_A('A'); end;", nativeQuery = true)
public void setStudentGradeToA();
}

因此,它使用本机查询来调用Set_GradesToA模式的STUDENT_PACKAGE包中的过程sch1

我目前正在测试Spring Boot应用程序的功能,并且它与Oracle数据库之间的集成。因此,我决定暂时使用内存数据库(H2)(带有Oracle兼容性选项)替换Oracle DB。 但是我该如何伪造这些Java打包过程?

我尝试如下在schema.sql(或data.sql)中创建别名:

CREATE SCHEMA if not exists sch1;
CREATE ALIAS sch1.STUDENT_PACKAGE AS $$ void Set_Grades_To_A(String s) { new String(s); } $$;

我真的不在乎Set_Grades_To_A过程中的内容,我关心的是如何定义它。

如上所述创建别名时,仍然出现语法错误。

Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "BEGIN SCH1[*].STUDENT_PACKAGE.Set_Grades_To_A('A'); END; "; SQL statement:
begin sch1.STUDENT_PACKAGE.Set_Grades_To_A('A'); end; [42000-197]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.message.DbException.getSyntaxError(DbException.java:203)

我想我有两个问题:

  1. 如何伪造sch1模式中Oracle软件包内部的存储过程?

  2. 为什么会出现上述语法错误?

2 个答案:

答案 0 :(得分:0)

这就是我所做的。

问题2:要回答此问题,我必须按以下方式更改本机查询

class FileManager : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit FileManager(QObject *parent = nullptr);
    enum RoleNames {
        INDEX = Qt::UserRole + 1,
        PATH,
        TYPE,
        CATEGORY
    };

    /**
     * @brief Opens a file
     * @param filePath The path to the file
     * @return false if the opening fails, true otherwise
     * Opens a file, and if successful, returns true and adds it to this model. Otherwise, it returns false.
     */
    Q_INVOKABLE
    bool openFile(QUrl filePath);

    Q_INVOKABLE
    GenericFile* getFile(int index) {
        if (index >= 0 && index < files.length()) {
            return files[index];
        }
        return nullptr;
    }

    Q_INVOKABLE
    ArchiveFile* getArchive(int index) {
        qDebug() << "Callled getArchive";
        try {
            return dynamic_cast<ArchiveFile*>(getFile(index));
        } catch (std::bad_cast e){
            return nullptr;
        }
    }

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QHash<int, QByteArray> roleNames() const override;

private:
    QList<GenericFile*> files;
};

问题1:涉及到三件事。现在,我已经如上所述更改了本机查询,我得到了另一个错误:

@Repository
public interface StudentRepository extends JpaRepository<Student, String> {

@Modifying
@Query(value = "call sch1.STUDENT_PACKAGE.Set_Grades_To_A('A')", nativeQuery = true)
public void setStudentGradeToA();
}

它正在寻找一个名为Caused by: org.h2.jdbc.JdbcSQLException: Database "sch1" not found; SQL statement: call sch1.STUDENT_PACKAGE.Set_Grades_To_A('A') [90013-197] at org.h2.message.DbException.getJdbcSQLException(DbException.java:357) at org.h2.message.DbException.get(DbException.java:179) at org.h2.message.DbException.get(DbException.java:155) 的数据库。似乎在H2中用于调用存储过程的模式是sch1。由于我不在乎该过程实际上是什么,因此我可以通过创建一个名为database.schema.procedure_name的数据库,一个名为sch1的模式和过程名称为STUDENT_PACKAGE

来伪造此信息

要创建内存数据库,必须在Set_Grades_To_A文件中设置以下属性spring.datasource.url

  1. 按照application.properties的方式创建sch1数据库。请注意,数据库名称为spring.datasource.url=jdbc:h2:mem:sch1;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS first_schema
  2. 通过将sch1添加到STUDENT_PACKAGE的末尾来创建\\;CREATE SCHEMA IF NOT EXISTS STUDENT_PACKAGE模式。这将添加另一个名为spring.datasource.url的架构。该属性应如下所示:STUDENT_PACKAGE
  3. 通过将spring.datasource.url=jdbc:h2:mem:sch1;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS first_schema\\;CREATE SCHEMA IF NOT EXISTS STUDENT_PACKAGE存储过程添加到schema.sql Set_Grades_To_A

答案 1 :(得分:0)

我能够通过添加IGNORE_CATALOGS=TRUE

来解决此问题
spring.datasource.url = jdbc:h2:mem:testdb;MODE=Oracle;IGNORE_CATALOGS=TRUE

这将忽略数据库名称