【问题标题】:Spring boot applicaiton unable to find SQLite jdbc driver classSpring Boot 应用程序找不到 SQLite jdbc 驱动程序类
【发布时间】:2022-01-21 01:30:58
【问题描述】:

在我的 Spring Boot 应用程序中,我指定了 sqlite jdbc 驱动程序的依赖项:

<dependency>
  <groupId>org.xerial</groupId>
  <artifactId>sqlite-jdbc</artifactId>
  <version>3.34.0</version>
</dependency>

在 pom.xml 属性中

<hibernate.version>5.1.0.Final</hibernate.version>

并在我的 application.properties 中有以下内容:

spring.jpa.database-platform=com.springboot.sqlite.SQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.defer-datasource-initialization = true

spring.datasource.url = jdbc:sqlite:cryptobot.db
spring.datasource.driver-class-name = org.sqlite.JDBC

我提供的 SQLDialect 类是从this article 复制而来的。 但是运行应用程序失败了

org.springframework.beans.factory.UnsatisfiedDependencyException:在类路径资源 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class] 中定义名称为“entityManagerFactory”的 bean 创建错误:通过方法表示的不满足的依赖关系“ entityManagerFactory'参数0;嵌套异常是 org.springframework.beans.factory.UnsatisfiedDependencyException:在类路径资源 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class] 中定义名称为 'entityManagerFactoryBuilder' 的 bean 创建错误:通过方法'表示不满足的依赖关系entityManagerFactoryBuilder'参数0;嵌套异常是 org.springframework.beans.factory.BeanCreationException:在类路径资源 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class] 中定义名称为“jpaVendorAdapter”的 bean 创建时出错:通过工厂方法进行 Bean 实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.orm.jpa.JpaVendorAdapter]:工厂方法“jpaVendorAdapter”抛出异常;嵌套异常是 java.lang.NoClassDefFoundError: org/hibernate/jpa/HibernatePersistenceProvider 在 org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.13.jar:5.3.13] 在 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.13.jar:5.3.13] 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.13.jar:5.3.13] 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.13.jar:5.3.13] 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-2.6.1.jar:2.6.1] 在 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.6.1.jar:2.6.1] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.1.jar:2.6.1] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.1.jar:2.6.1] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.1.jar:2.6.1] 在 com.binance.bot.BinancebotApplication.main(BinancebotApplication.java:10) ~[classes/:na]

这里出了什么问题?

【问题讨论】:

  • 嗨,您是否尝试过在不提供任何属性但 spring.datasource.url 的情况下运行它?当然 spring-boot-starter-data-jpa 也应该在依赖中。
  • @HughDarling 您是否通过扩展 org.hibernate.dialect.Dialect 配置了 SQLDialect
  • 是的,com.springboot.sqlite.SQLDialect 是我自己的,我实际上是从你提到的文章中复制的。
  • 我在几天后重试了,不知何故它现在显示了一个不同的错误:java.lang.NoClassDefFoundError: org/hibernate/jpa/HibernatePersistenceProvider
  • 请更新您的问题,其中包括最新的异常。最重要的是,您使用的是什么 spring-boot 版本?如果你告诉我这些信息,我可能会知道。

标签: spring-boot sqlite hibernate


【解决方案1】:

这个主要问题是您通过pom.xml中的以下配置明确配置为使用Hibernate 5.1.0

<hibernate.version>5.1.0.Final</hibernate.version>

太老了(6年前发布),spring-boot 2.6.1已经很久不支持了。

从技术上讲,spring-boot 2.6 基于 spring 5.3 而 spring 5.3 是针对 Hibernate 5.3+ 开发和测试的,并在运行时尽最大努力尝试与 Hibernate 5.2 向后兼容。您可以在 HibernateJpaVendorAdapterissue 的 javadoc 中找到此类信息。

它会尝试在某个时候加载org.hibernate.jpa.HibernatePersistenceProvider,但这个类只存在于 Hibernate 5.2 之后。由于您现在使用的是 Hibernate 5.1,因此它抱怨无法加载它并出现以下错误:

[org.springframework.orm.jpa.JpaVendorAdapter]:工厂方法 'jpaVendorAdapter' 抛出异常;嵌套异常是 java.lang.NoClassDefFoundError: org/hibernate/jpa/HibernatePersistenceProvider

所以只需在pom.xml 中删除上面的&lt;hibernate.version&gt;,这样它就会使用spring-boot 2.6.1 定义的h​​ibernate 5.6.1,然后您的问题就应该得到解决。对新项目使用非常旧的 Hibernate 版本是没有意义的。

【讨论】:

  • 我打印了类路径,我确实找到了 sqlite-jdbc 和其他一些 jdbcs,按以下顺序:org/springframework/boot/spring-boot-starter-jdbc/2.6.1/spring-boot -starter-jdbc-2.6.1.jar;org/springframework/spring-jdbc/5.3.13/spring-jdbc-5.3.13.jar;org/xerial/sqlite-jdbc/3.34.0/sqlite-jdbc-3.34 .0.jar
  • 我知道你提到你以某种方式解决了这个问题,现在我的回答与你的问题不匹配。我稍后会查看您更新的问题,然后更新我的答案。谢谢
  • 我在 pom.xml 中删除了 hibernate.version,但它仍在下载并在类路径中设置 hibernate 5.1.0 jar 并失败,HibernatePersistenceProvider 出现相同的 NoClassDefFound 错误。我不知道 5.1.0 最终版本是从哪里指定的。我做了一个 mvn clean install 但它没有改变任何东西。
  • @HughDarling 执行mvn dependency:tree ,它将显示pom.xml 中定义的哪些依赖项将包括hibernate 5.1.0。给我看这样的结果或整个pom.xml
  • 是的,它现在可以工作,确认是 IDE 问题。
【解决方案2】:

由于 Hibernate 没有附带 SQLite 方言,您可以按照以下路径进行操作:

1。通过扩展 Dialect 创建您自己的方言类。

import java.sql.Types;
import org.hibernate.dialect.Dialect;

public class SQLiteDialect extends Dialect {
 public SQLiteDialect() {
  super();
  registerColumnType(Types.BIT, "integer");
  registerColumnType(Types.TINYINT, "tinyint");
  registerColumnType(Types.SMALLINT, "smallint");
  registerColumnType(Types.INTEGER, "integer");
  registerColumnType(Types.BIGINT, "bigint");
  registerColumnType(Types.FLOAT, "float");
  registerColumnType(Types.REAL, "real");
  registerColumnType(Types.DOUBLE, "double");
  registerColumnType(Types.NUMERIC, "numeric");
  registerColumnType(Types.DECIMAL, "decimal");
  registerColumnType(Types.CHAR, "char");
  registerColumnType(Types.VARCHAR, "varchar");
  .
  .
  .
 }
}

Click 获取完整示例。

2。您可以使用第 3 方方言。

对于Hibernate 5,添加dependency

    <dependency>
        <groupId>com.github.gwenn</groupId>
        <artifactId>sqlite-dialect</artifactId>
        <version>0.1.2</version>
    </dependency>

和配置:

hibernate.dialect=org.sqlite.hibernate.dialect.SQLiteDialect

【讨论】:

    【解决方案3】:

    我试图在我的本地机器上复制这个,这里是解决方案。

    你必须通过扩展 org.hibernate.dialect 来创建自己的方言

    package com.mehul.SQLiteDemo.dialect;
    
    import java.sql.Types;
    
    import org.hibernate.dialect.Dialect;
    import org.hibernate.dialect.function.SQLFunctionTemplate;
    import org.hibernate.dialect.function.StandardSQLFunction;
    import org.hibernate.dialect.function.VarArgsSQLFunction;
    import org.hibernate.type.StringType;
    
    public class SQLDialect extends Dialect {
        public SQLDialect() {
            registerColumnType(Types.BIT, "integer");
            registerColumnType(Types.TINYINT, "tinyint");
            registerColumnType(Types.SMALLINT, "smallint");
            registerColumnType(Types.INTEGER, "integer");
            registerColumnType(Types.BIGINT, "bigint");
            registerColumnType(Types.FLOAT, "float");
            registerColumnType(Types.REAL, "real");
            registerColumnType(Types.DOUBLE, "double");
            registerColumnType(Types.NUMERIC, "numeric");
            registerColumnType(Types.DECIMAL, "decimal");
            registerColumnType(Types.CHAR, "char");
            registerColumnType(Types.VARCHAR, "varchar");
            registerColumnType(Types.LONGVARCHAR, "longvarchar");
            registerColumnType(Types.DATE, "date");
            registerColumnType(Types.TIME, "time");
            registerColumnType(Types.TIMESTAMP, "timestamp");
            registerColumnType(Types.BINARY, "blob");
            registerColumnType(Types.VARBINARY, "blob");
            registerColumnType(Types.LONGVARBINARY, "blob");
            // registerColumnType(Types.NULL, "null");
            registerColumnType(Types.BLOB, "blob");
            registerColumnType(Types.CLOB, "clob");
            registerColumnType(Types.BOOLEAN, "integer");
    
            registerFunction("concat", new VarArgsSQLFunction(StringType.INSTANCE, "", "||", ""));
            registerFunction("mod", new SQLFunctionTemplate(StringType.INSTANCE, "?1 % ?2"));
            registerFunction("substr", new StandardSQLFunction("substr", StringType.INSTANCE));
            registerFunction("substring", new StandardSQLFunction("substr", StringType.INSTANCE));
        }
    
        public boolean supportsIdentityColumns() {
            return true;
        }
    
        public boolean hasDataTypeInIdentityColumn() {
            return false; // As specify in NHibernate dialect
        }
    
        public String getIdentityColumnString() {
            // return "integer primary key autoincrement";
            return "integer";
        }
    
        public String getIdentitySelectString() {
            return "select last_insert_rowid()";
        }
    
        public boolean supportsLimit() {
            return true;
        }
    
        protected String getLimitString(String query, boolean hasOffset) {
            return new StringBuffer(query.length() + 20).append(query).append(hasOffset ? " limit ? offset ?" : " limit ?")
                    .toString();
        }
    
        public boolean supportsTemporaryTables() {
            return true;
        }
    
        public String getCreateTemporaryTableString() {
            return "create temporary table if not exists";
        }
    
        public boolean dropTemporaryTableAfterUse() {
            return false;
        }
    
        public boolean supportsCurrentTimestampSelection() {
            return true;
        }
    
        public boolean isCurrentTimestampSelectStringCallable() {
            return false;
        }
    
        public String getCurrentTimestampSelectString() {
            return "select current_timestamp";
        }
    
        public boolean supportsUnionAll() {
            return true;
        }
    
        public boolean hasAlterTable() {
            return false; // As specify in NHibernate dialect
        }
    
        public boolean dropConstraints() {
            return false;
        }
    
        public String getAddColumnString() {
            return "add column";
        }
    
        public String getForUpdateString() {
            return "";
        }
    
        public boolean supportsOuterJoinForUpdate() {
            return false;
        }
    
        public String getDropForeignKeyString() {
            throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect");
        }
    
        public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable,
                String[] primaryKey, boolean referencesPrimaryKey) {
            throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect");
        }
    
        public String getAddPrimaryKeyConstraintString(String constraintName) {
            throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect");
        }
    
        public boolean supportsIfExistsBeforeTableName() {
            return true;
        }
    
        public boolean supportsCascadeDelete() {
            return false;
        }
    }
    

    同时使用您的包和类名更新spring.jpa.database-platform=com.mehul.SQLiteDemo.dialect.SQLDialect

    注意:我用&lt;hibernate.version&gt;5.6.3.Final&lt;/hibernate.version&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 2020-03-08
      • 2011-04-12
      • 2016-11-02
      • 1970-01-01
      • 2020-02-08
      • 2014-10-14
      相关资源
      最近更新 更多