注意:不是教程只是笔记,如有错误欢迎批评指正
🍁简介
常用的数据库 sqlserver oracle mysql
Android嵌入式数据库SQLite
SQLite数据库支持SQL语法和ACID事务,适用于存储大量的关系型数据
eg:qq的聊天列表
学习强国的新闻
🌷创建数据库
创建数据库需要使用到一个抽象类SQLiteOpenHelper
抽象方法
它有两个抽象方法:
onCreate()
:创建数据库
onUpgrade()
:升级数据库
实例方法
getReadableDatabases()
和getWritableDatabases()
用于创建或打开一个数据库,返回一个可对数据读写操作的对象,两者的区别是:当数据库不可写入时(如磁盘满了),getReadableDatabases()
方法返回的对象将以只读的方式打开数据库,getWritableDatabases()
方法则会出现异常
构造方法
有3个构造方法可供重写,其中第一个参数少,用第一个构造方法有4个参数:
参数 | 解释 |
参数一 | context |
参数二 | 数据库名 |
参数三 | 查询数据时返回一个自定义的cursor,一般为null |
参数四 | 当前数据库的版本号,可用于对数据库进行升级操作 |
在onCreate
方法中,通过sqLiteDatabase.execSQL()
方法可以执行建表语句,如下我通过sql语句定义了一个user表,id为主键
DBOpenHelper完整代码
publicclassDBOpenHelperextendsSQLiteOpenHelper {
//构造方法
publicDBOpenHelper(@NullableContextcontext, @NullableStringname, @NullableSQLiteDatabase.CursorFactoryfactory, intversion) {
super(context, name, factory, version);
}
//创建数据库的表
@Override
publicvoidonCreate(SQLiteDatabasesqLiteDatabase) {
//建表
sqLiteDatabase.execSQL("create table user("+
"id integer "+
"primary key autoincrement,username "+
"varchar(20),password varchar(20),"+
"age integer)");
}
//更新数据库的表
@Override
publicvoidonUpgrade(SQLiteDatabasesqLiteDatabase, inti, inti1) {
}
}
在MainActivity
中我们与数据库建立连接并打开数据库
🌺操作数据
添加数据
然后我们在xml文件里添加几个按钮,通过按钮来对数据进行操作,添加数据有两种方式,
sqLiteDatabase.execSQL("")
方法执行sql语句添加- 通过
ContentValues
保存键值对添加
//方法二:
//类似hashmap,以键值对保存数据 key->数据表列名 value->列的值
ContentValuescontentValues=newContentValues();
contentValues.put("username","test1234");
contentValues.put("password","123456");
contentValues.put("age",19);
sqLiteDatabase.insert("user",null,contentValues);
在App Inspection
可以查看数据库的表结构
这种查看数据库表结构的方式必须要求虚拟机在API26及以上
数据库文件存放在/data/data/<package name>/databases/
目录下
老师&学长博客
这种传统的操作数据库的方法就记录这么多,老师和学长的博客都写的很详细啦
(3条消息) Android SQlite数据库使用详解Teacher.Hu的博客-CSDN博客android sqlite
MainActivity中完整代码
publicclassMainActivityextendsAppCompatActivity {
@Override
protectedvoidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建好数据库,并与数据库之间建立连接
DBOpenHelperdbOpenHelper=newDBOpenHelper(MainActivity.this,"test",null,1);
//打开数据库,返回一个可对数据读写操作的对象
SQLiteDatabasesqLiteDatabase=dbOpenHelper.getWritableDatabase();
findViewById(R.id.button1).setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(Viewview) {
//方法一:直接执行数据库执行语句
//sqLiteDatabase.execSQL("");
//方法二:
//类似hashmap,以键值对保存数据 key->数据表列名 value->列的值
ContentValuescontentValues=newContentValues();
contentValues.put("username","test1234");
contentValues.put("password","123456");
contentValues.put("age",19);
sqLiteDatabase.insert("user",null,contentValues);
}
});
}
}
🌳Room(官方第三方框架)
简介
使用 Room 将数据保存到本地数据库 | Android 开发者 | Android Developers (google.cn)
对数据库中的查询操作很是繁琐,为了更加专注Android内容的开发,官方对SQLliteOpenHelper
再封装,简化了开发者对数据库中数据的操作
- 针对 SQL 查询的编译时验证。
- 可最大限度减少重复和容易出错的样板代码的方便注解。
- 简化了数据库迁移路径。
使用
Room 包含三个主要组件:
- 数据库表实体,用于表示应用的数据库中的表。
- 数据访问对象 (DAO),提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法。
- 数据库类,用于保存数据库并作为应用持久性数据底层连接的主要访问点。
创建数据库表实体类
//使用 @Entity注解定义的类会被映射为数据库中的一张表。
//默认实体类的类名为表名,字段名为表名。当然我们也是可以修改的。
@Entity
publicclassUser1 {
//@PrimaryKey注解用来标注表的主键,
//并且使用autoGenerate = true 来指定了主键自增长
@PrimaryKey(autoGenerate=true)
publicintid;
publicStringuserName;
publicStringpassWord;
intage;
}
Dao数据操作工具接口
Dao类是一个 interface,其中定义了一系列的操作数据库的方法。Room为我们的提供了相关的注解,有@Insert、@Delete、@Update 和 @Query。
//Dao结尾的类 里面是数据库增删改查的方法
@Dao//
publicinterfaceUserDao {
//只需定义接口,无需实现
//表示是增加数据
@Insert
voidinsertUser(User1user1);
//删除数据
@Delete
voiddeleteUser(User1user1);
//查询数据
@Query("SELECT * FROM User1")
List<User1>findALLUser();
//精确匹配
@Query("SELECT * FROM User1 where id=:userId")
List<User1>findAllUserById(intuserId);
//模糊匹配
@Query("SELECT * FROM User1 where userName like '%'||:name|| '%'")
List<User1>findAllUserById(Stringname);
}
Database数据库对象抽象类
这是一个抽象类,并不真正的实现对数据库的连接和数据操作,而是定义抽象方法,让MainActivity
去实现
//建立数据库连接的抽象类
/*
1.创建
2.改造成抽象类
3.添加注解
4.定义获取数据库工具对象的抽象方法
*/
@Database(entities={User1.class},version=1,exportSchema=false)
publicabstractclassUserDaoDatabaseextendsRoomDatabase{
publicabstractUserDaogetUserDao();
}
@Database(entities={User1.class},version=1,exportSchema=false)
这其中的前两个参数好理解,一个是映射的数据库实体类,一个是数据库的版本号;Schema
是数据库的组织和结构,exportSchema
指暴露数据库的组织架构到一个文件夹,这个文件夹通过room.schemaLocation
指定。Schema
记录了数据库的组织和结构,并带有版本信息,所以不适合在发布的app中的文件夹中,而是最好指定到版本控制系统中,默认为true打开状态。所以最好是false。
MainActivity连接并调用数据库
publicclassMainActivityextendsAppCompatActivity {
UserDaouserDao;
UserDaoDatabaseuserDaoDatabase;
@Override
protectedvoidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.和数据库建立连接
userDaoDatabase=Room.databaseBuilder(this,UserDaoDatabase.class,"Mytest")
.allowMainThreadQueries()//允许在主线程调用
.build();
//2.返回的不是一个接口对象,返回的是一个接口的实现类 是运行期间动态生成的
userDao=userDaoDatabase.getUserDao();
//3.操作数据库
//增加数据
findViewById(R.id.button1).setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(Viewview) {
User1user1=newUser1();
user1.userName="starry";
user1.age=20;
user1.passWord="lx0411";
userDao.insertUser(user1);//接口的方法是不能够调用?为什么这里可以调用
}
});
//查询数据
findViewById(R.id.button2).setOnClickListener(
(view)->{
List<User1>user1List=userDao.findAllUserById(1);
for(User1user1:user1List){
Log.i("user1", "id: "+user1.id+" name: "+user1.userName);
}
}
);
//删除数据
findViewById(R.id.button3).setOnClickListener(
(view)->{
User1user1=newUser1();
user1.id=2;
userDao.deleteUser(user1);
}
);
}
}
每点击一次添加数据,表中就会新增一条数据
点击删除数据,可以看到id=2的数据已被删除
点击查询数据按钮,在日志打印台通过tag过滤日志可以看到,成功查询到id=1的记录
灵魂发问
最后有一个疑问为什么insertUser()方法可以直接被调用呢?我们都知道接口本身是不能被实例化的,不能直接调用。那么为什么这一行代码不会报错
userDao.insertUser(user1);//接口的方法是不能够调用?为什么这里可以调用
这是因为这一行代码:返回的不是一个接口对象,返回的是一个接口的实现类 是运行期间动态生成的
//2.返回的不是一个接口对象,返回的是一个接口的实现类 是运行期间动态生成的
userDao=userDaoDatabase.getUserDao();
如何查看这个动态生成的实现类呢?
可以看到这个动态生成的实现类都实现了接口中的方法