|
| 1 | +# Android数据库操作 |
| 2 | + |
| 3 | +需求:Android操作数据库的增、删、改、查 |
| 4 | + |
| 5 | +实现: |
| 6 | + |
| 7 | +1、新增学生基本信息 |
| 8 | + |
| 9 | +2、删除学生基本信息 |
| 10 | + |
| 11 | +3、修改学生基本信息 |
| 12 | + |
| 13 | +4、根据学号查姓名、根据姓名查学号、查询所有学生基本信息 |
| 14 | + |
| 15 | +运行展示 |
| 16 | + |
| 17 | +## 前置条件 |
| 18 | + |
| 19 | +1、SQLite不需要第三方依赖 |
| 20 | + |
| 21 | +2、Room |
| 22 | + |
| 23 | +```groovy |
| 24 | +implementation "androidx.room:room-runtime:2.2.5" |
| 25 | +annotationProcessor "androidx.room:room-compiler:2.2.5" |
| 26 | +``` |
| 27 | + |
| 28 | +3、LitePal |
| 29 | + |
| 30 | +```groovy |
| 31 | +implementation 'org.litepal.guolindev:core:3.2.2' |
| 32 | +``` |
| 33 | + |
| 34 | +4、MySQL |
| 35 | + |
| 36 | +```groovy |
| 37 | +implementation project(':xhttp2-lib') |
| 38 | +
|
| 39 | +implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" |
| 40 | +implementation "android.arch.lifecycle:runtime:1.1.1" |
| 41 | +``` |
| 42 | + |
| 43 | + |
| 44 | + |
| 45 | +源码 |
| 46 | + |
| 47 | +Github地址: |
| 48 | + |
| 49 | +https://github.com/littlecurl/AppProjects/blob/master/AndroidDatabaseDemo.zip |
| 50 | + |
| 51 | +Gitee地址: |
| 52 | + |
| 53 | +https://gitee.com/littlecurl/AppProjects/blob/master/AndroidDatabaseDemo.zip |
| 54 | + |
| 55 | +## 一、本地 |
| 56 | + |
| 57 | +[SQLite](https://www.runoob.com/sqlite/sqlite-tutorial.html)、Room、LitePal |
| 58 | + |
| 59 | +### 0、建库建表 |
| 60 | + |
| 61 | +#### 0.1 SQLite 建库建表相关代码 |
| 62 | + |
| 63 | +```java |
| 64 | +// SQLite建库建表 |
| 65 | +// 建库:DatabaseHelper 构造方法传入数据库名称 |
| 66 | +public DatabaseHelper(Context context, String name, CursorFactory factory, int version) { |
| 67 | + super(context, name, factory, version); |
| 68 | +} |
| 69 | +// 在 Application 中进行初始化 |
| 70 | +public static SQLiteDatabase sqliteDb; |
| 71 | +public static DatabaseHelper dbHelper; |
| 72 | + |
| 73 | +dbHelper = new DatabaseHelper(this); |
| 74 | +sqliteDb = dbHelper.getWritableDatabase(); |
| 75 | + |
| 76 | +// 建表:DatabaseHelper.onCreate() 方法中执行 SQL 语句 |
| 77 | +@Override |
| 78 | +public void onCreate(SQLiteDatabase db) { |
| 79 | + //创建数据库sql语句 并 执行 |
| 80 | + String studentSql = "CREATE TABLE " + STUDENT_INF + "(" + |
| 81 | + // 学生学号 |
| 82 | + "student_no varchar(20) PRIMARY KEY NOT NULL," + |
| 83 | + // 学生姓名 |
| 84 | + "name varchar(20) NOT NULL," + |
| 85 | + "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," + |
| 86 | + "update_time DATETIME DEFAULT CURRENT_TIMESTAMP" + |
| 87 | + ");"; |
| 88 | + db.execSQL(studentSql); |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +#### 0.2 Room 建库建表相关代码 |
| 93 | + |
| 94 | +```java |
| 95 | +// ROOM 建库建表 |
| 96 | +// 建库:使用 @Database 注解 |
| 97 | +@Database(entities = {StudentInf.class}, version = 1, exportSchema = false) |
| 98 | +public abstract class DemoDatabase extends RoomDatabase { |
| 99 | + public abstract StudentDao studentDao(); |
| 100 | +} |
| 101 | +// 在Application中调用databaseBuilder()传入数据库名,进行初始化 |
| 102 | +public static DemoDatabase roomDb; |
| 103 | +roomDb = Room.databaseBuilder(this, DemoDatabase.class, "demo_room").build(); |
| 104 | + |
| 105 | +// 建表:使用 @Entity 注解 |
| 106 | +// Entity,又叫 JavaBean,也叫 POJO |
| 107 | +// 如果一个类,只有一些属性和getter()、setter()、constructor()、toString()、equals()等方法,即可称之为Entity |
| 108 | +// 细分的话,还可以分成:DO(Data Object)、VO(View Object)、Model |
| 109 | +@Entity(tableName = "student_inf_room", indices = {@Index(value = "student_no")}) |
| 110 | +public class StudentInf { |
| 111 | + @PrimaryKey |
| 112 | + @ColumnInfo(name = "student_no") |
| 113 | + @NonNull |
| 114 | + private String studentNo; |
| 115 | + |
| 116 | + @ColumnInfo(name = "name") |
| 117 | + @NonNull |
| 118 | + private String name; |
| 119 | + |
| 120 | + // 省略getter()、setter()、constructor()、toString()、equals() |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +#### 0.3 LitePal 建库建表相关代码 |
| 125 | + |
| 126 | +```java |
| 127 | +// LitePal建库建表 |
| 128 | +// 建库:在 assets 目录下新建 litepal.xml 配置数据库名、表相关的Model |
| 129 | +<?xml version="1.0" encoding="utf-8"?> |
| 130 | +<litepal> |
| 131 | + <dbname value="demo_litepal" /> |
| 132 | + |
| 133 | + <version value="1" /> |
| 134 | + |
| 135 | + <list> |
| 136 | + <mapping class="cn.edu.heuet.demo.litepal.model.Student" /> |
| 137 | + </list> |
| 138 | + |
| 139 | + <storage value="external" /> |
| 140 | +</litepal> |
| 141 | +// 然后在 Application 中初始化 |
| 142 | +// 内部调用了 Operator.initialize(context) ,所以很多操作也可以使用 Operator |
| 143 | +LitePal.initialize(this); |
| 144 | + |
| 145 | +// 建表:model类 extends LitePalSupport |
| 146 | +public class Student extends LitePalSupport { |
| 147 | + // LitePal默认会创建上id字段,所以这里不写也行 |
| 148 | + private long id; |
| 149 | + // 注意,LitePal会把所有驼峰命名转为统一小写字母 |
| 150 | + private String studentNo; |
| 151 | + private String name; |
| 152 | + // 省略getter()、setter()、constructor()、toString()、equals() |
| 153 | +} |
| 154 | +``` |
| 155 | + |
| 156 | +#### 0.4 MySQL 建库建表相关代码 |
| 157 | + |
| 158 | +这里不做过多介绍,更多请参考相关书籍、视频、[博客](https://www.liaoxuefeng.com/wiki/1177760294764384) |
| 159 | + |
| 160 | + |
| 161 | + |
| 162 | +### 1、新增 |
| 163 | + |
| 164 | + 单个新增、批量新增 |
| 165 | + |
| 166 | + 冲突解决策略(根据返回值判断是否新增成功) |
| 167 | + |
| 168 | +#### 1.1 SQLite 新增相关代码 |
| 169 | + |
| 170 | +```java |
| 171 | +// SQLite新增: |
| 172 | +// 单个新增:DatabaseHelper 中调用 insertWithOnConflict 可以指定冲突策略,这里的 4 表示 " OR IGNORE " |
| 173 | +// CONFLICT_VALUES{"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; |
| 174 | +db.insertWithOnConflict(tableName, null, contentValues, 4); |
| 175 | + |
| 176 | +// 批量新增 |
| 177 | +多次调用 insertWithOnConflict() |
| 178 | +``` |
| 179 | + |
| 180 | +#### 1.2 Room 新增相关代码 |
| 181 | + |
| 182 | +```java |
| 183 | +// 单个新增:StudentDao 中使用 @Insert 注解,可以指定冲突策略 |
| 184 | +@Insert(onConflict = OnConflictStrategy.IGNORE) |
| 185 | +void insert(StudentInf studentInf); |
| 186 | + |
| 187 | +// 批量新增:只需要将参数类型修改为 集合 即可 |
| 188 | +@Insert(onConflict = OnConflictStrategy.IGNORE) |
| 189 | +void insertAll(List<StudentInf> studentInfs); |
| 190 | +``` |
| 191 | + |
| 192 | +#### 1.3 LitePal 新增相关代码 |
| 193 | + |
| 194 | +```java |
| 195 | +// 单个新增:初始化 Model 对象完成后,调用父类 save() 方法即可 |
| 196 | +Student student1 = new Student(1, "sno2021001", "littlecurl"); |
| 197 | +student1.save(); |
| 198 | + |
| 199 | +// 批量新增 |
| 200 | +多次调用 save() 方法 |
| 201 | +// 或者使用Operator的saveAll() |
| 202 | +Operator.saveAll(students); |
| 203 | +``` |
| 204 | + |
| 205 | +#### 1.4 MySQL 新增相关代码 |
| 206 | + |
| 207 | +这里不做过多介绍,更多请参考相关书籍、视频、[博客](https://www.liaoxuefeng.com/wiki/1177760294764384) |
| 208 | + |
| 209 | +### 2、删除 |
| 210 | + |
| 211 | + 根据主键删除 |
| 212 | + |
| 213 | +#### 2.1 SQLite 删除相关代码 |
| 214 | + |
| 215 | +```java |
| 216 | +// SQLite的删除,在 DatabaseHelper 中调用 delete() |
| 217 | +db.delete(STUDENT_INF, "student_no=?", studentNos); |
| 218 | +``` |
| 219 | + |
| 220 | +#### 2.2 Room 删除相关的代码 |
| 221 | + |
| 222 | +```java |
| 223 | +// Room的删除,在 StudentDao 中使用 @Delete 注解 |
| 224 | +@Delete |
| 225 | +void delete(StudentInf studentInf); |
| 226 | +``` |
| 227 | + |
| 228 | +#### 2.3 LitePal 删除相关代码 |
| 229 | + |
| 230 | +```java |
| 231 | +// 调用 LitePal.deleteAll() |
| 232 | +LitePal.deleteAll(Student.class, "studentno=?", getStudentNo()); |
| 233 | +// 或者调用 Operator.deleteAll() |
| 234 | +Operator.deleteAll(Student.class, "studentno=?", getStudentNo()); |
| 235 | + |
| 236 | +// 不传任何参数即表示清空表 |
| 237 | +LitePal.deleteAll(Student.class); |
| 238 | +Operator.deleteAll(Student.class); |
| 239 | +``` |
| 240 | + |
| 241 | +#### 2.4 MySQL 删除相关代码 |
| 242 | + |
| 243 | +这里不做过多介绍,更多请参考相关书籍、视频、[博客](https://www.liaoxuefeng.com/wiki/1177760294764384) |
| 244 | + |
| 245 | + |
| 246 | + |
| 247 | +### 3、修改 |
| 248 | + |
| 249 | + 根据主键修改 |
| 250 | + |
| 251 | +#### 3.1 SQLite 修改相关代码 |
| 252 | + |
| 253 | +```java |
| 254 | +// SQLite 的修改: |
| 255 | +// 在 DatabaseHelper 中调用 update() |
| 256 | +db.update(STUDENT_INF, values, "student_no=?", studentNos); |
| 257 | +``` |
| 258 | + |
| 259 | +#### 3.2 Room 修改相关代码 |
| 260 | + |
| 261 | +```java |
| 262 | +// Room 的修改: |
| 263 | +// 在 StudentDao 中使用 @Update 注解 |
| 264 | +@Update |
| 265 | +void update(StudentInf studentInf); |
| 266 | +``` |
| 267 | + |
| 268 | +#### 3.3 LitePal 修改相关代码 |
| 269 | + |
| 270 | +```java |
| 271 | +// LitePal 的修改 |
| 272 | +// 初始化model后,调用 updateAll() 这里可以直接拼接参数 |
| 273 | +Student student = new Student(getStudentNo(), getStudentName()); |
| 274 | +student.updateAll("studentno=?", getStudentNo()); |
| 275 | +// 或者使用 Operator |
| 276 | +ContentValues values = new ContentValues(); |
| 277 | +values.put("name",getStudentName()); |
| 278 | +Operator.updateAll(Student.class,values,"studentno=?", getStudentNo()); |
| 279 | +``` |
| 280 | + |
| 281 | +#### 3.4 MySQL 修改相关代码 |
| 282 | + |
| 283 | +这里不做过多介绍,更多请参考相关书籍、视频、[博客](https://www.liaoxuefeng.com/wiki/1177760294764384) |
| 284 | + |
| 285 | + |
| 286 | + |
| 287 | +### 4、查询 |
| 288 | + |
| 289 | + 单个查询、批量查询 |
| 290 | + |
| 291 | +#### 4.1 SQLite 查询相关代码 |
| 292 | + |
| 293 | +```java |
| 294 | +// SQLite的查询: |
| 295 | +// 在 DatabaseHelper 写好方法 |
| 296 | +public String getNameByStudentNo(SQLiteDatabase db, String... studentNos) { |
| 297 | + // (String table, String[] columns, |
| 298 | + // String selection,String[] selectionArgs, String groupBy, String having,String orderBy) |
| 299 | + Cursor cursor = db.query(STUDENT_INF, new String[]{"name"}, "student_no=?", studentNos, null, null, null); |
| 300 | + StringBuilder nameBuilder = new StringBuilder(); |
| 301 | + while (cursor.moveToNext()) { |
| 302 | + String name = cursor.getString(cursor.getColumnIndex("name")); |
| 303 | + nameBuilder.append(name).append("\n"); |
| 304 | + } |
| 305 | + cursor.close(); // 关闭游标,释放资源 |
| 306 | + return nameBuilder.toString(); |
| 307 | +} |
| 308 | +``` |
| 309 | + |
| 310 | +#### 4.2 Room 查询相关代码 |
| 311 | + |
| 312 | +```java |
| 313 | +// Room的查询: |
| 314 | +// 在 StudentDao 中使用 @Query 注解,执行 SQL |
| 315 | +@Query("SELECT name FROM student_inf_room WHERE student_no = :studentNo") |
| 316 | +String getNameByStudentNo(String studentNo); |
| 317 | +``` |
| 318 | + |
| 319 | +#### 4.3 LitePal 查询相关代码 |
| 320 | + |
| 321 | +```java |
| 322 | +// LitePal的查询 |
| 323 | +// 使用 LitePal.findBySQL() 执行 SQL |
| 324 | +Cursor cursor = LitePal.findBySQL("SELECT name FROM student WHERE studentno = ?", studentNo); |
| 325 | +StringBuilder nameBuilder = new StringBuilder(); |
| 326 | +while (cursor.moveToNext()) { |
| 327 | + name = cursor.getString(cursor.getColumnIndex("name")); |
| 328 | + nameBuilder.append(name).append("\n"); |
| 329 | +} |
| 330 | +cursor.close(); // 关闭游标,释放资源 |
| 331 | +result = nameBuilder.toString(); |
| 332 | +``` |
| 333 | + |
| 334 | + |
| 335 | + |
| 336 | +#### 4.4 MySQL 查询相关代码 |
| 337 | + |
| 338 | +这里不做过多介绍,更多请参考相关书籍、视频、[博客](https://www.liaoxuefeng.com/wiki/1177760294764384) |
| 339 | + |
| 340 | + |
| 341 | + |
| 342 | + |
| 343 | + |
| 344 | +## 二、远程 |
| 345 | + |
| 346 | +Xhttp2 + 花生壳 + Mysql |
| 347 | + |
| 348 | + |
| 349 | + |
| 350 | +### Android端 |
| 351 | + |
| 352 | +1、打开项目之前修改版本号 |
| 353 | + |
| 354 | +2、AndroidManifest.xml 中配置允许 http 访问、配置 Application、配置 Activity |
| 355 | + |
| 356 | +3、多模块引入方式 |
| 357 | + |
| 358 | + 依赖引入无法修改源码,模块引入可以修改源码 |
| 359 | + |
| 360 | +4、dataBinding 介绍 |
| 361 | + |
| 362 | + |
| 363 | + |
| 364 | +### 花生壳 |
| 365 | + |
| 366 | +1、CMD黑窗口 查看 IPv4 地址:ipconfig |
| 367 | + |
| 368 | +2、检测内外穿透是否成功 |
| 369 | + |
| 370 | +3、有时候需要重启 |
| 371 | + |
| 372 | + |
| 373 | + |
| 374 | +### 后端 |
| 375 | + |
| 376 | +1、MySQL 相关 |
| 377 | + |
| 378 | + 版本 |
| 379 | + |
| 380 | + 可视化工具 |
| 381 | + |
| 382 | +2、Maven 相关 |
| 383 | + |
| 384 | + 版本 |
| 385 | + |
| 386 | + 配置 |
| 387 | + |
| 388 | +3、MyBatis 与 SpringBoot 等内容请参考龙虾三少的课程[《SpringBoot构建电商基础秒杀项目》](https://www.imooc.com/view/1079) |
| 389 | + |
0 commit comments