spring boot 项目 JPA+SQLite 无法启动

使用spring data JPA搭配SQLite数据库无法启动,打印如下错误

INFO  o.s.d.j.r.config.DialectResolver >>> Couldn't determine Dialect for "sqlite" 
WARN  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext >>> Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbcMappingContext' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Unsatisfied dependency expressed through method 'jdbcMappingContext' parameter 1: Error creating bean with name 'jdbcCustomConversions' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Failed to instantiate [org.springframework.data.jdbc.core.convert.JdbcCustomConversions]: Factory method 'jdbcCustomConversions' threw exception with message: Error creating bean with name 'jdbcDialect' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Failed to instantiate [org.springframework.data.relational.core.dialect.Dialect]: Factory method 'jdbcDialect' threw exception with message: Cannot determine a dialect for org.springframework.jdbc.core.JdbcTemplate@3fd01d2d; Please provide a Dialect 

原因是同时引入了spring-boot-starter-data-jdbc的依赖,将其从pom中删除,仅保留spring-boot-starter-data-jpa和sqlite-jdbc以及hibernate-community-dialects三个和数据库有关的依赖包即可。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-community-dialects</artifactId>
</dependency>

此时项目正常启动

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Spring Boot 中实现 SQLite 加密功能,可以使用 SQLite 的 SQLCipher 扩展。SQLCipher 是一个基于 SQLite 的加密数据库,提供了加密和解密 SQLite 数据库的方法。 下面是实现步骤: 1. 添加 SQLCipher 依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>net.zetetic</groupId> <artifactId>android-database-sqlcipher</artifactId> <version>4.4.0</version> </dependency> ``` 2. 配置 SQLite 数据库 在 application.properties 文件中配置 SQLite 数据库,设置加密密码等信息,例如: ```properties spring.datasource.driver-class-name=org.sqlite.JDBC spring.datasource.url=jdbc:sqlite:test.db spring.datasource.username= spring.datasource.password= spring.datasource.tomcat.initial-size=1 spring.datasource.tomcat.max-active=5 spring.datasource.tomcat.min-idle=1 spring.datasource.tomcat.max-idle=5 # Enabling SQLCipher for SQLite spring.jpa.database-platform=com.example.sqlite.Platform spring.datasource.sql-script-encoding=UTF-8 ``` 其中,`com.example.sqlite.Platform` 是一个自定义的数据库平台类,用于启用 SQLCipher 扩展。在这个类中,我们需要指定 SQLCipher 的加密密码,例如: ```java public class Platform extends SQLiteDialect { private static final String CIPHER_ALGORITHM = "256"; @Override public String getAddPrimaryKeyString(String constraintName) { return " primary key"; } @Override public boolean supportsIdentityColumns() { return true; } @Override public boolean hasDataTypeInIdentityColumn() { return false; } @Override public String getIdentityColumnString() { return "integer"; } @Override public String getIdentitySelectString() { return "select last_insert_rowid()"; } @Override public String getSequenceNextValString(String sequenceName) { return "select " + sequenceName + ".nextval from dual"; } @Override public String getCreateSequenceString(String sequenceName) { return "create sequence " + sequenceName; } @Override public String getDropSequenceString(String sequenceName) { return "drop sequence " + sequenceName; } @Override public String getLimitString(String sql, boolean hasOffset) { return new StringBuffer(sql.length() + 20).append(sql).append(hasOffset ? " limit ? offset ?" : " limit ?").toString(); } @Override public boolean bindLimitParametersInReverseOrder() { return true; } @Override public boolean supportsLimitOffset() { return true; } @Override public boolean supportsVariableLimit() { return false; } @Override public String getQuerySequencesString() { return null; } @Override public String getTableTypeString() { return " engine=sqlite"; } @Override public boolean supportsIfExistsBeforeTableName() { return true; } @Override public boolean supportsColumnCheck() { return false; } @Override public boolean supportsPartitionBy() { return false; } @Override public boolean supportsNoColumnsInsert() { return true; } @Override public boolean supportsCascadeDelete() { return false; } @Override public String getForUpdateString() { return " for update"; } @Override public String getWriteLockString(int timeout) { return " for update"; } @Override public String getReadLockString(int timeout) { return " lock in share mode"; } @Override public String getReadLockString() { return " lock in share mode"; } @Override public boolean supportsOuterJoinForUpdate() { return false; } @Override public boolean supportsIfExistsAfterTableName() { return false; } @Override public boolean supportsTupleDistinctCounts() { return false; } @Override public boolean supportsValuesList() { return true; } @Override public boolean supportsRowValueConstructorSyntax() { return true; } @Override public boolean supportsRowValueConstructorSyntaxInInList() { return true; } @Override public boolean useFollowOnLocking() { return false; } @Override public String getSelectClauseNullString(int sqlType) { return "null"; } @Override public boolean supportsUnionAll() { return true; } @Override public boolean supportsCommentOn() { return false; } @Override public boolean supportsTemporaryTables() { return true; } @Override public String getCreateTemporaryTableString() { return "create temporary table"; } @Override public String getCreateTemporaryTablePostfix() { return ""; } @Override public boolean dropTemporaryTableAfterUse() { return true; } @Override public boolean supportsCurrentTimestampSelection() { return true; } @Override public boolean isCurrentTimestampSelectStringCallable() { return false; } @Override public String getCurrentTimestampSelectString() { return "select current_timestamp"; } @Override public boolean supportsUnion() { return true; } @Override public boolean supportsCommentOnTable() { return false; } @Override public boolean supportsIfExistsBeforeConstraintName() { return false; } @Override public boolean supportsNotNullUnique() { return true; } @Override public boolean supportsExistsInSelect() { return true; } @Override public boolean supportsLobValueChangePropogation() { return false; } @Override public boolean supportsSubqueryOnMutatingTable() { return false; } @Override public String getSelectGUIDString() { return "select hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-a' || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))"; } @Override public boolean supportsLockTimeouts() { return false; } @Override public String getForUpdateNowaitString() { return getForUpdateString(); } @Override public boolean supportsTupleDistinctCountsMultiDimensionalArray() { return false; } @Override public boolean supportsTuplesInSubqueries() { return true; } @Override public boolean supportsSubqueryOnMutatingTableBelow() { return false; } @Override public boolean supportsSubqueryOnMutatingTableAbove() { return false; } @Override public boolean supportsCircularCascadeDeleteConstraints() { return false; } @Override public boolean supportsEmptyInList() { return true; } @Override public boolean supportsExpectedLobUsagePattern() { return false; } @Override public boolean supportsParameterizedInList() { return true; } @Override public boolean requiresCastingOfParametersInSelectClause() { return true; } @Override public boolean supportsRowValueConstructorSyntaxInUpdate() { return true; } @Override public boolean supportsSkipLocked() { return false; } @Override public boolean supportsNoWait() { return false; } @Override public boolean supportsIgnore() { return false; } @Override public boolean supportsValuesClause() { return true; } @Override public boolean supportsWindowFunctions() { return false; } @Override public boolean supportsRowValueConstructorSyntaxWhenDerived() { return true; } @Override public boolean supportsNationalizedTypes() { return false; } @Override public boolean supportsJdbcConnectionLobCreation() { return false; } @Override public String getResultSetWithHoldabilitySuffix(String sql) { return sql; } @Override public String getCreateTableString() { return "create table if not exists"; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } @Override public boolean supportsLockTimeouts() { return false; } } ``` 在这个类中,我们重写了 SQLite 的一些方法,以启用 SQLCipher 扩展。其中,`CIPHER_ALGORITHM` 是 SQLCipher 的加密算法,这里设置为 256。 3. 加密 SQLite 数据库 在运行时,Spring Boot 会自动创建 SQLite 数据库,并使用 SQLCipher 进行加密。如果需要在已有的 SQLite 数据库上启用加密,可以使用下面的代码: ```java import net.sqlcipher.database.SQLiteDatabase; public class SQLiteEncryption { public static void main(String[] args) { SQLiteDatabase.loadLibs(); String databasePath = "/path/to/database.db"; String password = "password"; SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databasePath, password, null); // execute SQL statements here database.close(); } } ``` 其中,`loadLibs` 方法会加载 SQLCipher 库,`openOrCreateDatabase` 方法会打开或创建一个 SQLite 数据库,并使用指定的密码进行加密。在这个方法中,可以执行 SQL 语句等操作。最后,需要关闭数据库连接。 4. 测试 SQLCipher 加密功能 可以使用以下代码测试 SQLCipher 加密功能: ```java import net.sqlcipher.Cursor; import net.sqlcipher.database.SQLiteDatabase; public class SQLiteEncryption { public static void main(String[] args) { SQLiteDatabase.loadLibs(); String databasePath = "/path/to/database.db"; String password = "password"; SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databasePath, password, null); // execute SQL statements here database.execSQL("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"); database.execSQL("INSERT INTO users (name, email) VALUES (?, ?)", new Object[]{"John Doe", "john.doe@example.com"}); Cursor cursor = database.rawQuery("SELECT * FROM users", new String[]{}); while (cursor.moveToNext()) { int id = cursor.getInt(0); String name = cursor.getString(1); String email = cursor.getString(2); System.out.println(id + "\t" + name + "\t" + email); } cursor.close(); database.close(); } } ``` 这个代码会创建一个名为 `users` 的表,插入一条数据,并查询所有数据并输出。如果一切正常,应该能够顺利执行,并输出查询结果。 注意:在使用 SQLCipher 时,需要使用 `net.sqlcipher.database.SQLiteDatabase` 和 `net.sqlcipher.Cursor` 类替换原来的 `android.database.sqlite.SQLiteDatabase` 和 `android.database.Cursor` 类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值