当前位置: 首页 > news >正文

SQLite在安卓中的应用

在 Android 应用程序中,SQLite 是默认的嵌入式数据库解决方案,Android 系统为开发者提供了相应的 API 来管理 SQLite 数据库。通过使用 SQLiteOpenHelper 类和 SQLiteDatabase 类,开发者可以方便地创建、查询、更新和删除数据库中的数据。

以下是关于如何在 Android 中使用 SQLite 的详细介绍和示例。


一、在 Android 中使用 SQLite 的步骤

1. 创建 SQLiteOpenHelper 类

SQLiteOpenHelper 是一个辅助类,用于管理数据库的创建和版本管理。它提供了两个重要的方法:

  • onCreate(SQLiteDatabase db):当数据库第一次创建时调用。
  • onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库需要升级时调用。

示例:创建 SQLiteOpenHelper 子类

public class MyDatabaseHelper extends SQLiteOpenHelper {private static final String DATABASE_NAME = "MyDatabase.db";  // 数据库名称private static final int DATABASE_VERSION = 1;                // 数据库版本public MyDatabaseHelper(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION);}// 第一次创建数据库时调用@Overridepublic void onCreate(SQLiteDatabase db) {// 创建数据库中的表String CREATE_TABLE = "CREATE TABLE users ("+ "id INTEGER PRIMARY KEY AUTOINCREMENT,"+ "name TEXT NOT NULL,"+ "age INTEGER,"+ "email TEXT);";db.execSQL(CREATE_TABLE);}// 当数据库版本升级时调用@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 如果表已存在则删除,重新创建db.execSQL("DROP TABLE IF EXISTS users");onCreate(db);}
}
  • DATABASE_NAME 定义了数据库的名称。
  • DATABASE_VERSION 是数据库的版本号,每当数据库结构发生变化时,需要升级版本号。
  • onCreate() 方法在数据库首次创建时调用,执行 SQL 语句来创建数据库中的表。
  • onUpgrade() 方法在数据库需要升级时调用,可以用于处理表结构的变更。
2. 打开数据库

使用 SQLiteOpenHelper 类时,可以通过调用 getWritableDatabase()getReadableDatabase() 方法来打开数据库。前者允许执行写操作,而后者只允许执行读操作。

MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();
3. 插入数据

使用 insert() 方法将数据插入到表中。

// 创建一个 ContentValues 对象,用于存储键值对
ContentValues values = new ContentValues();
values.put("name", "Alice");
values.put("age", 25);
values.put("email", "alice@example.com");// 插入数据
long newRowId = db.insert("users", null, values);
  • ContentValues 类用于保存列名与列值的映射。
  • insert() 方法将数据插入到指定的表中,返回插入数据的行 ID。
4. 查询数据

使用 query() 方法从数据库中查询数据。该方法返回一个 Cursor 对象,用于遍历查询结果。

// 定义要查询的列
String[] projection = {"id","name","age","email"
};// 查询数据
Cursor cursor = db.query("users",   // 表名projection,   // 要返回的列null,         // WHERE 子句null,         // WHERE 子句的参数null,         // GROUP BY 子句null,         // HAVING 子句null          // 排序方式
);// 遍历查询结果
while (cursor.moveToNext()) {long userId = cursor.getLong(cursor.getColumnIndexOrThrow("id"));String userName = cursor.getString(cursor.getColumnIndexOrThrow("name"));int userAge = cursor.getInt(cursor.getColumnIndexOrThrow("age"));String userEmail = cursor.getString(cursor.getColumnIndexOrThrow("email"));
}// 关闭游标
cursor.close();
  • projection 定义了需要查询的列。
  • Cursor 对象用于从查询结果中提取数据,moveToNext() 方法用于遍历结果集。
5. 更新数据

使用 update() 方法更新表中的数据。

// 创建 ContentValues 对象
ContentValues values = new ContentValues();
values.put("age", 26);// 更新记录
String selection = "name = ?";
String[] selectionArgs = { "Alice" };int count = db.update("users",    // 表名values,     // 要更新的值selection,  // WHERE 子句selectionArgs  // WHERE 子句的参数
);
  • update() 方法根据指定的条件更新表中的记录,返回受影响的行数。
6. 删除数据

使用 delete() 方法删除表中的数据。

// 定义删除条件
String selection = "name = ?";
String[] selectionArgs = { "Alice" };// 删除记录
int deletedRows = db.delete("users", selection, selectionArgs);
  • delete() 方法根据指定的条件删除表中的记录,返回删除的行数。

二、数据库操作的异步处理

在 Android 中,数据库操作通常需要在子线程中进行,以避免在主线程上执行耗时操作,防止阻塞 UI。

可以使用 AsyncTaskHandlerThreadJetpack 提供的 Room 库来简化和管理异步的数据库操作。

使用 Room 作为 SQLite 的抽象层

Room 是 Android Jetpack 提供的一个持久性库,它简化了与 SQLite 的交互,并且支持异步查询。使用 Room 可以避免手动编写大量的 SQL 代码,并提供类型安全的 API。

Room 的基础组件:
  1. 实体 (Entity):对应数据库中的表。
  2. DAO (Data Access Object):定义数据操作方法。
  3. 数据库 (Database):数据库持有者,管理实体和 DAO。

示例:使用 Room 管理数据库

  1. 定义实体类:
@Entity
public class User {@PrimaryKey(autoGenerate = true)public int id;public String name;public int age;public String email;
}
  1. 定义 DAO 接口:
@Dao
public interface UserDao {@Insertvoid insertUser(User user);@Query("SELECT * FROM User WHERE id = :id")User getUserById(int id);@Updatevoid updateUser(User user);@Deletevoid deleteUser(User user);
}
  1. 创建数据库类:
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {public abstract UserDao userDao();
}
  1. 初始化 Room 数据库:
AppDatabase db = Room.databaseBuilder(getApplicationContext(),AppDatabase.class, "MyDatabase").build();// 在子线程中执行数据库操作
new Thread(() -> {User user = new User();user.name = "Alice";user.age = 25;user.email = "alice@example.com";db.userDao().insertUser(user);
}).start();

三、SQLite 数据库备份和恢复

由于 SQLite 数据存储在一个单一的文件中,因此备份和恢复操作非常简单。可以直接复制数据库文件来备份或恢复数据。

备份数据库文件:

File dbFile = context.getDatabasePath("MyDatabase.db");
File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");try (FileChannel src = new FileInputStream(dbFile).getChannel();FileChannel dst = new FileOutputStream(backupFile).getChannel()) {dst.transferFrom(src, 0, src.size());
} catch (IOException e) {e.printStackTrace();
}

恢复数据库文件:

File dbFile = context.getDatabasePath("MyDatabase.db");
File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");try (FileChannel src = new FileInputStream(backupFile).getChannel();FileChannel dst = new FileOutputStream(dbFile).getChannel()) {dst.transferFrom(src, 0, src.size());
} catch (IOException e) {e.printStackTrace();
}

四、SQLite 数据库的性能优化

  1. 使用索引:为经常查询的列创建索引可以显著提升查询速度。

    CREATE INDEX idx_user_name ON users(name);
    
  2. 事务处理:将多个操作放在一个事务中执行,可以减少磁盘 I/O,从而提高性能。

    BEGIN TRANSACTION;
    -- 执行多条 SQL 语句
    COMMIT;
    
  3. 按需加载数据:在查询大量数据时,使用分页查询减少内存消耗。

    SELECT * FROM users LIMIT 10 OFFSET 20;
    

通过上述步骤,开发者可以轻松在 Android 中集成并使用 SQLite 数据库。为了进一步深入理解,接下来将继续介绍 SQLite 在 Android 中的性能优化、常见的最佳实践,以及在不同场景下的高级用法。


五、SQLite 在 Android 中的性能优化

SQLite 数据库在 Android 应用中处理小规模数据时表现非常优异,但当数据量增大时,可能会面临性能问题。以下是几种常见的性能优化方法:

1. 使用事务

将多条 SQL 操作放在一个事务中可以显著提升数据库操作的效率。SQLite 的每一条独立的插入或更新操作都会触发一次磁盘写操作,增加了 I/O 的开销。如果将多条插入或更新操作包裹在同一个事务中,则只会有一次磁盘写入,减少了 I/O 操作,极大提高了性能。

示例:使用事务插入多条记录

db.beginTransaction();
try {for (User user : userList) {ContentValues values = new ContentValues();values.put("name", user.getName());values.put("age", user.getAge());values.put("email", user.getEmail());db.insert("users", null, values);}db.setTransactionSuccessful();  // 标记事务成功
} finally {db.endTransaction();  // 结束事务
}
  • db.beginTransaction() 开启事务。
  • db.setTransactionSuccessful() 在事务成功时调用。
  • db.endTransaction() 结束事务。
2. 使用索引 (Indexing)

为常用查询的列创建索引,可以加速查询速度。索引本质上是表中特定列的排序结构,它减少了查询时的扫描行数。

创建索引的示例:

CREATE INDEX idx_user_name ON users(name);

注意,虽然索引可以加快查询速度,但也会增加插入和更新操作的开销,因此应根据需要平衡索引的使用。

3. 减少数据查询

在查询数据时,避免使用 SELECT * 来检索所有列,尽量只查询需要的列,减少不必要的数据传输。

示例:只查询需要的列

String[] projection = {"id","name"
};
Cursor cursor = db.query("users",projection,null,null,null,null,null
);
4. 使用批量操作

在处理大批量数据操作时,使用批量插入、更新或删除可以提高操作效率。批量操作可以通过事务和 SQLiteStatement 提高性能。

批量插入示例:

SQLiteStatement stmt = db.compileStatement("INSERT INTO users (name, age, email) VALUES (?, ?, ?)");db.beginTransaction();
try {for (User user : userList) {stmt.bindString(1, user.getName());stmt.bindLong(2, user.getAge());stmt.bindString(3, user.getEmail());stmt.execute();stmt.clearBindings();}db.setTransactionSuccessful();
} finally {db.endTransaction();
}
5. 使用 PRAGMA 进行性能调优

SQLite 提供了许多 PRAGMA 命令,允许开发者动态配置数据库的行为,从而提升性能。例如:

  • PRAGMA synchronous = OFF;:关闭同步写入,提升写入速度(在数据一致性不是首要关注时使用)。
  • PRAGMA journal_mode = WAL;:将数据库设置为“写入时日志”模式,这样可以在高并发读写的场景下提升性能。

示例:设置 WAL 模式

PRAGMA journal_mode = WAL;

在 WAL 模式下,写操作不会直接覆盖原数据,而是记录在日志中,并在空闲时间将日志内容合并回主数据库文件,从而提高并发读写的性能。


六、SQLite 的最佳实践

1. 善用 ContentValues 和 Cursor
  • 使用 ContentValues 来存储插入或更新的数据,不仅简化了代码,还提高了可读性。
  • 使用 Cursor 遍历查询结果时,始终在使用后关闭 Cursor,防止内存泄漏。

关闭 Cursor 示例:

Cursor cursor = db.query("users", null, null, null, null, null, null);
try {while (cursor.moveToNext()) {// 获取数据}
} finally {cursor.close();  // 确保 cursor 关闭
}
2. 使用 Room 框架

在复杂的 Android 应用程序中,直接使用 SQLite 可能会导致 SQL 语句冗长、难以维护。为了简化与 SQLite 的交互,推荐使用 Room 框架,它提供了类型安全的 API,并能与 LiveData 和 RxJava 轻松集成,实现异步查询操作。

3. 避免在主线程进行数据库操作

数据库操作可能会耗时较长,尤其是在处理大数据集或网络存储时。为了避免 UI 卡顿,务必在工作线程中执行数据库操作。可以使用 AsyncTaskExecutorService 或 Room 提供的异步操作方法。

示例:使用 ExecutorService 进行异步操作

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {// 在后台线程中执行数据库操作db.userDao().insertUser(user);
});
4. 确保数据库版本管理

当数据库的结构发生变化时,需要通过增加数据库的版本号并在 onUpgrade() 中进行适当的迁移操作,以确保数据的完整性。

版本升级示例:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {if (oldVersion < 2) {db.execSQL("ALTER TABLE users ADD COLUMN phone TEXT");}
}

通过这种方式,可以安全地向数据库表中添加新字段,而不会破坏现有数据。


七、SQLite 高级用法

1. 数据库加密

Android 系统默认的 SQLite 数据库是不加密的。如果需要对敏感数据进行加密,可以使用 SQLCipher 这样的第三方库。SQLCipher 是对 SQLite 的增强版,提供了对数据库文件的透明加密支持。

使用 SQLCipher 加密数据库:

  1. 添加依赖:
implementation 'net.zetetic:android-database-sqlcipher:4.5.0'
  1. 创建或打开加密数据库:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFile, "your-password", null);

通过加密,数据在数据库文件中存储时将是加密的,即使文件被拷贝,未经授权的用户也无法直接查看数据。

2. 数据库迁移

当应用程序的数据库架构需要更新时,必须处理好数据迁移。Room 框架提供了方便的迁移机制,可以帮助开发者在数据库版本升级时保持数据的完整性。

Room 迁移示例:

Migration MIGRATION_1_2 = new Migration(1, 2) {@Overridepublic void migrate(@NonNull SupportSQLiteDatabase database) {database.execSQL("ALTER TABLE users ADD COLUMN phone TEXT");}
};Room.databaseBuilder(context, AppDatabase.class, "MyDatabase").addMigrations(MIGRATION_1_2).build();

通过 Room 的迁移功能,数据库的版本升级变得更加安全和可控。

3. 数据库备份与恢复

SQLite 的备份和恢复操作可以通过文件操作来实现。开发者可以直接复制 SQLite 数据库文件以创建备份,或者通过将文件移动到安全的存储位置来进行恢复。

示例:备份数据库文件到外部存储

File dbFile = context.getDatabasePath("MyDatabase.db");
File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");try (FileChannel src = new FileInputStream(dbFile).getChannel();FileChannel dst = new FileOutputStream(backupFile).getChannel()) {dst.transferFrom(src, 0, src.size());
} catch (IOException e) {e.printStackTrace();
}

示例:从备份文件恢复数据库

File dbFile = context.getDatabasePath("MyDatabase.db");
File backupFile = new File(Environment.getExternalStorageDirectory(), "MyDatabase_backup.db");try (FileChannel src = new FileInputStream(backupFile).getChannel();FileChannel dst = new FileOutputStream(dbFile).getChannel()) {dst.transferFrom(src, 0, src.size());
} catch (IOException e) {e.printStackTrace();
}

总结

SQLite 是一个轻量、可靠、简单易用的数据库解决方案,特别适合嵌入式系统和移动应用中的数据存储需求。通过 Android 提供的 API,开发者可以轻松地实现数据持久化功能。在实际开发中

相关文章:

SQLite在安卓中的应用

在 Android 应用程序中&#xff0c;SQLite 是默认的嵌入式数据库解决方案&#xff0c;Android 系统为开发者提供了相应的 API 来管理 SQLite 数据库。通过使用 SQLiteOpenHelper 类和 SQLiteDatabase 类&#xff0c;开发者可以方便地创建、查询、更新和删除数据库中的数据。 以…...

Python数据库操作

前面的章节中学习了使用 Python 读写文件的方法&#xff0c;大家可以用文件方式来存放数据&#xff0c;不过使用文件方式时不容易管理&#xff0c;同时还容易丢失&#xff0c;会带来许多问题。目前主流的方法都是采用数据库软件&#xff0c;通过数据库软件来组织和存放数据&…...

交叉熵损失函数为代表的两层神经网络的反向传播量化求导计算公式

反向传播&#xff08;back propagation&#xff0c;BP&#xff09;算法也称误差逆传播&#xff0c;是神经网络训练的核心算法。我们通常说的 BP 神经网络是指应用反向传播算法进行训练的神经网络模型。反向传播算法的工作机制究竟是怎样的呢&#xff1f;我们以一个两层&#xf…...

数据结构——八大排序(上)

数据结构中的八大排序算法是计算机科学领域经典的排序方法&#xff0c;它们各自具有不同的特点和适用场景。以下是这八大排序算法的详细介绍&#xff1a; 一、插入排序&#xff08;Insertion Sort&#xff09; 核心思想&#xff1a;将数组中的所有元素依次跟前面已经排好的元…...

vxe-table 导入导出功能全解析

一、vxe-table 导入导出功能概述 vxe-table 的导入导出功能在数据处理中具有至关重要的作用。在现代数据管理和处理的场景中&#xff0c;高效地导入和导出数据是提高工作效率的关键。 对于导入功能而言&#xff0c;它允许用户将外部的表格数据&#xff0c;如 Excel 文件&…...

常用STL的操作以及特点

C 标准模板库&#xff08;STL&#xff09;提供了很多常用的数据结构和算法&#xff0c;极大简化了开发工作。STL 包括容器&#xff08;如 vector、list、map 等&#xff09;、算法&#xff08;如排序、查找等&#xff09;以及迭代器。以下是一些常用 STL 容器的操作以及它们的特…...

025 elasticsearch索引管理-Java原生客户端

文章目录 pom.xml1创建索引2.创建索引并设置settings信息3.创建索引并设置mapping信息4.删除索引库5.给未设置mapping的索引设置mapping elasticsearch版本7.10.2&#xff0c;要求java客户端与之相匹配&#xff0c;推荐Springboot版本是2.3以上版本 依赖配置使用的是JUnit 5&am…...

Gin框架操作指南10:服务器与高级功能

官方文档地址&#xff08;中文&#xff09;&#xff1a;https://gin-gonic.com/zh-cn/docs/ 注&#xff1a;本教程采用工作区机制&#xff0c;所以一个项目下载了Gin框架&#xff0c;其余项目就无需重复下载&#xff0c;想了解的读者可阅读第一节&#xff1a;Gin操作指南&#…...

AIGC技术的学习 系列一

文章目录 前言一、AIGC技术演进1.1 图像视频生成1.2. 文本生成1.3. 多模态生成1.4. 小结二、CAD&CAE软件介绍2.1. CAD软件2.2. CAE软件2.3. 小结三、AIGC技术与CAD&CAE软件的集成案例3.1. 土建设计领域3.2. 机械设计领域四、结语五、参考文献总结前言 在全球智能制造的…...

Milvus×Dify半小时轻松构建RAG系统

最近&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术在AI界引起了广泛关注。作为一种将知识库与生成模型结合的新型架构&#xff0c;RAG大大提升了AI应用的实际表现。而在构建RAG系统时&#xff0c;Milvus作为业界领先的开源向量数据库&#xff0c;扮演着关键角色。本…...

wireshark 解密浏览器https数据包

一、导出浏览器证书有两种方法 1、在浏览器快捷方式追加启动参数&#xff1a; --ssl-key-log-file"d:\log\2.log" C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe --ssl-key-log-file"d:\log\2.log" 2、环境变量中新建用…...

【HTML】构建网页的基石

我的主页&#xff1a;2的n次方_ HTML 是一种超文本标记语言&#xff0c;不仅有文本&#xff0c;还能包含图片&#xff0c;音频等 1. HTML 的文件基本结构 html 标签是整个 html 文件的最顶层标签&#xff0c;head 标签中写页面的属性&#xff0c;body 标签是页面中显示的…...

rust不允许在全局区定义普通变量!

文章目录 C 中的全局变量Rust 中的全局变量设计哲学的体现 在 C 和 Rust 中&#xff0c;全局变量的处理方式体现了这两种语言设计哲学上的一些根本性差异&#xff1a; C 中的全局变量 C 允许在全局作用域中定义变量。这些变量在程序的整个生命周期内都存在&#xff0c;从程序开…...

量化投资中的数据驱动决策:大数据如何改变金融市场

随着科技的进步&#xff0c;金融行业迎来了前所未有的变革&#xff0c;量化投资作为其中的代表&#xff0c;逐渐成为投资市场的主流。量化投资是基于数学模型、数据分析以及算法策略的投资方式&#xff0c;与传统依赖经验和直觉的投资方法相比&#xff0c;它的核心优势在于能够…...

MySQL 设计数据表

一个数据表主要包含信息有 : 表名、主键、字段、数据类型、索引&#xff0c;本节主要介绍表的命名规范、字段命名、字段的数据类型选择。 新建的表都是新建在 “item_name” 数据库中的&#xff0c;新建 “item_name” 数据库命令如下 : CREATE DATABASE item_name;新建数据库…...

【大数据技术基础 | 实验一】配置SSH免密登录

文章目录 一、实验目的二、实验要求三、实验原理&#xff08;一&#xff09;大数据实验一体机&#xff08;二&#xff09;SSH免密认证 四、实验环境五、实验内容和步骤&#xff08;一&#xff09;搭建集群服务器&#xff08;二&#xff09;添加域名映射&#xff08;三&#xff…...

地级市碳排放效率测算2006-2021年

为了测算碳排放效率&#xff0c;研究者们采用了多种方法&#xff0c;其中超效率SBM&#xff08;Slack-Based Measure&#xff09;和超效率CCR&#xff08;Charnes, Cooper and Rhodes&#xff09;模型是常用的两种方法。这些模型可以有效地评估决策单元的相对有效性&#xff0c…...

周易解读:四象

四 象 在前面呢&#xff0c;我是讲完了太极与两仪的知识。这一节&#xff0c;我们来讲解四象的内容。 关于四象的知识&#xff0c;它在正式的周易的经文里面&#xff0c;它并没有多少用处。但是呢&#xff0c;在基础知识的学习里面&#xff0c;四象的知识&#xff0c;大家是…...

Java设计模式梳理:行为型模式(策略,观察者等)

行为型模式 行为型模式关注的是各个类之间的相互作用&#xff0c;将职责划分清楚&#xff0c;使得我们的代码更加地清晰。 策略模式 策略模式太常用了&#xff0c;所以把它放到最前面进行介绍。它比较简单&#xff0c;我就不废话&#xff0c;直接用代码说事吧。 下面设计的…...

【MySQL】入门篇—基本数据类型:使用LIMIT限制结果集

为了提高查询效率和用户体验&#xff0c;MySQL提供了LIMIT子句&#xff0c;用于限制查询结果的行数。LIMIT不仅可以提高性能&#xff0c;还可以帮助用户快速获取所需的数据&#xff0c;尤其在分页显示数据时非常有用。 应用场景&#xff1a; 分页显示&#xff1a;在网页应用中…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...