Android SqlDelight详解和Demo例子文档格式.docx
《Android SqlDelight详解和Demo例子文档格式.docx》由会员分享,可在线阅读,更多相关《Android SqlDelight详解和Demo例子文档格式.docx(31页珍藏版)》请在冰点文库上搜索。
![Android SqlDelight详解和Demo例子文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/2/cec0f49c-0e36-4932-80cf-42635e2fddbc/cec0f49c-0e36-4932-80cf-42635e2fddbc1.gif)
这里编写创建表和查询的语句;
createtableuser(
_idINTEGERNOTNULLPRIMARYKEYAUTOINCREMENT,
nameTEXTNOTNULL,
ageINTEGERNOTNULL
);
--其他的语句通过标识符来引用。
在生成的Java对象中会包含
--一个该标识符的常亮引用这个语句。
--查询use表,百分号(%)代表零个、一个或多个数字或字符,||连接两个不同的字符串,得到一个新的字符串。
select_by_name:
select*fromuser;
2.生成接口Module
编写完毕sql语句之后,make一下moduel,即可在build/generated/source/sqldelight/包名/看到xxxModule接口文件(xxx就是你的sq文件的名称)。
可以看到接口大概是这样的。
publicinterfaceUserModel{
StringTABLE_NAME="
user"
;
String_ID="
_id"
StringNAME="
name"
StringAGE="
age"
StringCREATE_TABLE="
"
+"
createtableuser(\r\n"
_idINTEGERNOTNULLPRIMARYKEYAUTOINCREMENT,\r\n"
nameTEXTNOTNULL,\r\n"
ageINTEGERNOTNULL\r\n"
)"
long_id();
@NonNull
Stringname();
longage();
interfaceCreator<
TextendsUserModel>
{
Tcreate(long_id,@NonNullStringname,longage);
}
finalclassMapper<
implementsRowMapper<
T>
privatefinalFactory<
userModelFactory;
publicMapper(Factory<
userModelFactory){
this.userModelFactory=userModelFactory;
@Override
publicTmap(@NonNullCursorcursor){
returnuserModelFactory.creator.create(
cursor.getLong(0),
cursor.getString
(1),
cursor.getLong
(2)
);
finalclassMarshal{
protectedfinalContentValuescontentValues=newContentValues();
Marshal(@NullableUserModelcopy){
if(copy!
=null){
this._id(copy._id());
this.name(copy.name());
this.age(copy.age());
publicContentValuesasContentValues(){
returncontentValues;
publicMarshal_id(long_id){
contentValues.put("
_id);
returnthis;
publicMarshalname(Stringname){
name);
publicMarshalage(longage){
age);
finalclassFactory<
publicfinalCreator<
creator;
publicFactory(Creator<
creator){
this.creator=creator;
/**
*@deprecatedUsecompiledstatements(
*/
@Deprecated
publicMarshalmarshal(){
returnnewMarshal(null);
publicMarshalmarshal(UserModelcopy){
returnnewMarshal(copy);
publicSqlDelightStatementselect_by_name(){
returnnewSqlDelightStatement("
select*fromuser"
newString[0],Collections.<
String>
singleton("
));
publicMapper<
select_by_nameMapper(){
returnnewMapper<
(this);
}
从这个接口可以看到重要的有下面四个类和接口:
Mapper
把Cursor映射为Java对象
Marshal
把Java对象转换为ContentValues,好方便插入数据库
接口Creator
里面定义了一个方法create用来创建我们的Model类型(这里用的是泛型T)
Factory
里面包含一个实现了Creator对象的creator,如果有列值需要转换的话还要包括相应的ColumnAdapter,它的构造函数传入Creator和ColumnAdapter这些参数,marshal方法返回Mode的Marshal(通过它的asContentValues获取对应的ContentValues)
3.定义Bean类
这里利用AtuoValue重写接口,因为SqlDelight生成的接口适合AutoValue无缝接入的,AutoValue的作用的是,自动生成bean代码,AutoValue请点击我。
使用需要导包
//基础AutoValue
apt'
com.google.auto.value:
auto-value:
1.4-rc3'
provided'
//AutoValue的扩展,为每个AutoValue注释对象创建一个简单的GsonTypeAdapterFactory。
//
com.ryanharter.auto.value:
auto-value-gson:
0.4.6'
//AutoValue的扩展,支持Android的Parcelable
auto-value-parcel:
0.2.5'
//可选择TypeAdapter支持
compile'
auto-value-parcel-adapter:
这时候User的bean为
@AutoValue
publicabstractclassUserimplementsUserModel{
publicstaticfinalFactory<
User>
FACTORY=newFactory<
>
(newCreator<
(){
publicUsercreate(long_id,@NonNullStringname,longage){
//AutoValue_User需要先make一下module
returnnewAutoValue_User(_id,name,age);
});
publicstaticfinalRowMapper<
SELECT_ALL_MAPPER=FACTORY.select_by_nameMapper();
4.使用
然后写一个Activity来测试看看(Sqlite相关知识请XX,点我看教程):
publicclassMainActivityextendsAppCompatActivity{
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建获取名字为tp的数据库
SQLiteDatabasesqLiteDatabase=newStuDBHelp(this,"
tp"
null,1).getWritableDatabase();
//插入数据
sqLiteDatabase.insert("
null,createContentValues(0,"
天平"
21));
null,createContentValues(1,"
逼辉"
23));
Log.e("
@@"
"
数据数量:
:
"
+getAllUsers(sqLiteDatabase).size());
publicList<
getAllUsers(SQLiteDatabasedb){
List<
result=newArrayList<
();
//try-with-resources写法,括号里面的资源需要继承AutoCloseable,作用是可以自动关闭对象
try(Cursorcursor=db.rawQuery(User.FACTORY.select_by_name().statement,newString[0])){
while(cursor.moveToNext()){
result.add(User.SELECT_ALL_MAPPER.map(cursor));
returnresult;
publicContentValuescreateContentValues(intid,Stringname,intage){
ContentValuescontentValues=newContentValues();
id);
name);
age);
classStuDBHelpextendsSQLiteOpenHelper{
publicStuDBHelp(Contextcontext,Stringname,SQLiteDatabase.CursorFactoryfactory,intversion){
super(context,name,factory,version);
//第一次创建数据库的调用的方法
publicvoidonCreate(SQLiteDatabasedb){
//db.execSQL(User.CREATE_TABLE);
//创建表
db.execSQL(User.CREATE_TABLE);
publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){
这时候你会看到输出:
2
2.3sq语句参数
.sq文件使用与SQLite完全相同的语法,包括SQLite绑定args(官方文档点我)。
如果语句包含绑定args,将在Factory上生成类型安全方法,该方法返回包含查询字符串,查询args和要查询的表的字段的SqlDelightStatement。
上面的例子中,我把sq文件里面的查询语句添加where条件,变成:
select*fromuserwherename='
天平'
然后重新make一下module,然后修改查询的getAllUsers方法:
publicList<
//创建SqlDelightStatement对象,里面有查询字符串和参数
SqlDelightStatementquery=User.FACTORY.select_by_name("
//try_with_resources写法,括号里面的资源需要继承AutoCloseable,作用是可以自动关闭对象
try(Cursorcursor=db.rawQuery(User.FACTORY.select_by_name("
).statement,query.args)){
此时可以看到输出:
1
如果是数组就用IN:
select_by_names:
select*fromuserwherenamein?
SqlDelightStatementquery=User.FACTORY.select_by_name(newString[]{"
"
});
try(Cursorcursor=db.rawQuery(query.statement,query.args)){
还能用运算符,例如查询user表的name字段是天开头的或结尾的:
?
1标识参数为同一个的意思
select*fromuserwhere
namelike'
%'
||?
1
or
namelike?
1||'
SqlDelightStatementquery=User.FACTORY.select_by_name("
天"
Cursorcursor=db.rawQuery(query.statement,query.args)
2.4插入、更新、删除
执行多次的插入,更新和删除都需要make一下module,SQLDelight会为为它们生成一个类型安全类。
例如在User.sq添加一句:
--更新name为参数1的年龄为参数2
update_age:
updateusersetage=?
wherename=?
重新make一下module会看到UserModel有一个Update_age类:
finalclassUpdate_ageextendsSqlDelightCompiledStatement.Update{
publicUpdate_age(SQLiteDatabasedatabase){
super("
pileStatement("
publicvoidbind(longage,@NonNullStringname){
program.bindLong(1,age);
program.bindString(2,name);
更新的时候(在上面的栗子的MainActivity的onCreate修改):
//创建Update_age对象
User.Update_ageupdateAge;
updateAge=newUser.Update_age(sqLiteDatabase);
//设置修改的值
updateAge.bind(66,"
updateAge.bind(99,"
//执行
updateAge.program.execute();
//执行,返回修改的行数,这个方法只修改最后一个
//updateAge.program.executeUpdateDelete();
for(Useruser:
getAllUsers(sqLiteDatabase)){
user:
+user.toString());
这时候会看到输出:
User{_id=0,name=天平,age=66}
User{_id=1,name=逼辉,age=99}
ps:
注意:
如果是bind了多个,executeUpdateDelete只能修改最后那个。
如果需要同时修改需要使用execute,如上面的代码
2.5多个结果
选择返回多个结果列的话,要为查询生成的结果自定义模型、映射程序和工厂方法。
例如:
在User.sq底部添加语句:
--根据age分组,group_concat链接所有的相同age的名字(默认使用逗号链接)
names_for_age:
selectage,group_concat(name)
fromuser
groupbyage;
在Userbean里面添加一个类和静态常量:
//
returnnewAutoV