学习鸿蒙应用开发,在DataAbility这里卡了好久,因为官方文档太简单了,漏掉了很多的东西,还好网上已经有大神已经做出来了,我查查资料,也做出自己的Demo来了。

首先,在模块的build.gradle文件中添加compileOptions{            annotationEnabled true    }

apply plugin: 'com.huawei.ohos.hap'
ohos {
    compileSdkVersion 4
    defaultConfig {
        compatibleSdkVersion 3
    }
    compileOptions{            annotationEnabled true    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
    testCompile'junit:junit:4.12'
}

不添加的话,数据库的相关类的的包无法识别。

同步以后就可以创建数据库的类BookStore了:

package com.example.dataabilitydemo;

import ohos.data.orm.OrmDatabase;
import ohos.data.orm.annotation.Database;

@Database(entities = {User.class}, version = 1)
public abstract class BookStore extends OrmDatabase {
}

然后再创建数据表User了:

package com.example.dataabilitydemo;

import ohos.data.orm.OrmObject;
import ohos.data.orm.annotation.Entity;
import ohos.data.orm.annotation.Index;
import ohos.data.orm.annotation.PrimaryKey;

@Entity(tableName = "user", ignoredColumns = {"ignoreColumn1", "ignoreColumn2"},
        indices = {@Index(value = {"firstName", "lastName"}, name = "name_index", unique = true)})
public class User extends OrmObject {
    // 此处将userId设为了自增的主键。注意只有在数据类型为包装类型时,自增主键才能生效。
    @PrimaryKey(autoGenerate = true)
    private Integer userId;
    private String firstName;
    private String lastName;
    private int age;
    private double balance;
    private int ignoreColumn1;
    private int ignoreColumn2;
    // 开发者自行添加字段的getter和setter 方法。

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public int getIgnoreColumn1() {
        return ignoreColumn1;
    }

    public void setIgnoreColumn1(int ignoreColumn1) {
        this.ignoreColumn1 = ignoreColumn1;
    }

    public int getIgnoreColumn2() {
        return ignoreColumn2;
    }

    public void setIgnoreColumn2(int ignoreColumn2) {
        this.ignoreColumn2 = ignoreColumn2;
    }
}

下面就可以创建DataAbility了

鸿蒙devEco链接 mysql数据库 鸿蒙数据库开发_鸿蒙

有人说创建的时候要勾选visible,可是我这根本就没有这个选项,不过没关系,名字就叫UserDataAbility

鸿蒙devEco链接 mysql数据库 鸿蒙数据库开发_鸿蒙devEco链接 mysql数据库_02

创建后,配置config,

"abilities": [
      ...........
      {
        "visible": true,
        "permissions": [
          "com.example.dataabilitydemo.UserDataAbility.DATA"
        ],
        "name": "com.example.dataabilitydemo.UserDataAbility",
        "icon": "$media:icon",
        "description": "$string:userdataability_description",
        "type": "data",
        "uri": "dataability://com.example.dataabilitydemo.UserDataAbility"
      }
    ]

其中"visible": true就是弥补创建页面没有visible勾选项的,permissions,name,uri这些项的值不一定非得是包名+类名,但保险起见,大家还是按规矩来。

然后就可以编辑UserDataAbility类了,首先,定义全局变量,并在onStart方法实现DatabaseHelper对象,用来操作数据库,并插入一条数据。

rivate String uriString="dataability://com.example.dataabilitydemo.UserDataAbility";//这里要跟config.json中的URI保持一致
    private static final String DATABASE_NAME ="BookStore.db";
    private static final String DATABASE_NAME_ALIAS = "BookStore";
    private static OrmContext ormContext = null;
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "My_log");

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        DatabaseHelper helper = new DatabaseHelper(this); 
        ormContext = helper.getOrmContext(DATABASE_NAME_ALIAS, DATABASE_NAME, BookStore.class);
        User user = new User();
        user.setFirstName("Zhang");
        user.setLastName("San");
        user.setAge(29);
        user.setBalance(100.51);
        boolean isSuccessed = ormContext.insert(user);
        isSuccessed = ormContext.flush();
        HiLog.info(LABEL_LOG, "ProviderAbility onStart");
    }

然后重写query方法,用来查询:

@Override
    public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
        HiLog.info(LABEL_LOG, "ProviderAbility query");
        if(ormContext == null){
            HiLog.error(LABEL_LOG,"failed to query, ormContext is null");
            return null;
        }
        //查询数据库
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, User.class);
        ResultSet resultSet = ormContext.query(ormPredicates,columns);
        if (resultSet == null){
            HiLog.info(LABEL_LOG,"resultSet is null");
        }
        return resultSet;
    }

最后,在MainAbilitySlice来调用,其他的Ability要是访问DataAbility,就需要在config.json中授予访问权限,如下

"orientation": "unspecified",
        "name": "com.example.dataabilitydemo.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "DataAbilityDemo",
        "type": "page",
        "launchType": "standard",
         //下面的name要跟DataAbility里的permissions保持一致呀
        "reqPermissions": [ { "name": "com.example.dataabilitydemo.UserDataAbility.DATA" }]

配置完就可以在Slice里写代码啦:

public class MainAbilitySlice extends AbilitySlice {
    //下面的uriString要与config.json中DataAbility的uri保持一致,但是坑爹的事他有三个斜杠
    private String uriString = "dataability:///com.example.dataabilitydemo.UserDataAbility";
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "My_log");
    private DataAbilityHelper helper;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        helper = DataAbilityHelper.creator(this);
        Button btnDataSelect = (Button) findComponentById(ResourceTable.Id_btn_data_select);
        if (btnDataSelect != null) {
            // 为按钮设置点击回调
            btnDataSelect.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    try {
                        queryDataAbility();
                    } catch (DataAbilityRemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    public void queryDataAbility() throws DataAbilityRemoteException {
        // 构造查询条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo("lastName", "San");
        // 进行查询
        String[] columns = new String[]{"firstName"};
        Uri uri = Uri.parse(uriString);
        ResultSet resultSet = helper.query(uri, columns, predicates);
        // 处理结果
        HiLog.info(LABEL_LOG, "queryDataAbilitystart");
        resultSet.goToFirstRow();
        do {
            // 在此处理ResultSet中的记录;
            HiLog.info(LABEL_LOG, "firstName=" + resultSet.getString(0));
        } while (resultSet.goToNextRow());
    }
}

就是单击按钮,查询一个lastName叫san的人他的firstName:

12-31 21:37:18.617 22937-5343/? I 01100/My_log: ProviderAbility onStart
12-31 21:37:26.628 22937-22937/com.example.dataabilitydemo I 01100/My_log: ProviderAbility query
12-31 21:37:26.632 22937-22937/com.example.dataabilitydemo I 01100/My_log: queryDataAbilitystart
12-31 21:37:26.633 22937-22937/com.example.dataabilitydemo I 01100/My_log: firstName=Zhang

简单的查询功能就完成啦。

既然查询能走通,那么继续试试其他的,先插入一条数据吧,首先重新DataAbility的insert方法:

@Override
    public int insert(Uri uri, ValuesBucket value) {
// 参数校验
        HiLog.info(LABEL_LOG, "UserDataAbility insert");
        if (ormContext == null) {
            HiLog.error(LABEL_LOG, "failed to insert, ormContext is null");
            return -1;
        }

        // 构造插入数据
        User user = new User();
        user.setUserId(value.getInteger("userId"));
        user.setFirstName(value.getString("firstName"));
        user.setLastName(value.getString("lastName"));
        user.setAge(value.getInteger("age"));
        user.setBalance(value.getDouble("balance"));

        // 插入数据库
        boolean isSuccessed = true;
        isSuccessed = ormContext.insert(user);
        if (!isSuccessed) {
            HiLog.error(LABEL_LOG, "failed to insert");
            return -1;
        }
        isSuccessed = ormContext.flush();
        if (!isSuccessed) {
            HiLog.error(LABEL_LOG, "failed to insert flush");
            return -1;
        }
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        int id = Math.toIntExact(user.getRowId());
        HiLog.info(LABEL_LOG, "UserDataAbility insert id="+id);
        return id;
    }

在Slice中先调用插入,然后再查询我们插入的数据:

public void queryDataAbility() throws DataAbilityRemoteException {
        // 构造查询条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo("lastName", "史蒂夫");
        // 进行查询
        String[] columns = new String[]{"firstName"};
        Uri uri = Uri.parse(uriString);
        ResultSet resultSet = helper.query(uri, columns, predicates);
        // 处理结果
        HiLog.info(LABEL_LOG, "queryDataAbilitystart");
        resultSet.goToFirstRow();
        do {
            // 在此处理ResultSet中的记录;
            HiLog.info(LABEL_LOG, "firstName=" + resultSet.getString(0));
        } while (resultSet.goToNextRow());
    }
    public void insertDataAbility() throws DataAbilityRemoteException {
        // 构造插入数据
        HiLog.info(LABEL_LOG, "MainAbilitySlice insertDataAbility");
        DataAbilityHelper helper = DataAbilityHelper.creator(this);
        Uri uri = Uri.parse(uriString);
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString("firstName", "孬蛋");
        valuesBucket.putString("lastName", "史蒂夫");
        valuesBucket.putInteger("age", 12);
        valuesBucket.putDouble("balance", 200.0);
        helper.insert(uri, valuesBucket);
    }

日志输出:

01-01 09:18:21.256 20487-20487/com.example.dataabilitydemo I 01100/My_log: MainAbilitySlice insertDataAbility
01-01 09:18:21.262 20487-20487/com.example.dataabilitydemo I 01100/My_log: UserDataAbility insert
01-01 09:18:21.270 20487-20487/com.example.dataabilitydemo I 01100/My_log: UserDataAbility insert id=2
01-01 09:18:30.485 20487-20487/com.example.dataabilitydemo I 01100/My_log: ProviderAbility query
01-01 09:18:30.505 20487-20487/com.example.dataabilitydemo I 01100/My_log: queryDataAbilitystart
01-01 09:18:30.506 20487-20487/com.example.dataabilitydemo I 01100/My_log: firstName=孬蛋

再试试修改我们插入的数据,重写DataAbility的update方法:

@Override
    public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
        if (ormContext == null) {
            HiLog.error(LABEL_LOG, "failed to update, ormContext is null");
            return -1;
        }

        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
        int index = ormContext.update(ormPredicates, value);
        HiLog.info(LABEL_LOG, "UserDataAbility update value:" + index);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        return index;
    }

在Slice中,更新刚插入的数据,修改她的名字,然后再查询:

public void updateDataAbility() throws DataAbilityRemoteException {
        // 构造插入数据
        DataAbilityHelper helper = DataAbilityHelper.creator(this);

// 构造更新条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo("lastName", "史蒂夫");

// 构造更新数据
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString("firstName", "小精豆");
        valuesBucket.putInteger("age", 12);
        Uri uri = Uri.parse(uriString);
        try {
            helper.update(uri, valuesBucket, predicates);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }

结果(一定要先插入,再查询):

01-01 10:21:47.149 26565-26565/com.example.dataabilitydemo I 01100/My_log: ProviderAbility query
01-01 10:21:47.156 26565-26565/com.example.dataabilitydemo I 01100/My_log: queryDataAbilitystart
01-01 10:21:47.157 26565-26565/com.example.dataabilitydemo I 01100/My_log: firstName=孬蛋
01-01 10:21:51.961 26565-26565/com.example.dataabilitydemo I 01100/My_log: MainAbilitySlice updateDataAbility
01-01 10:21:51.966 26565-26565/com.example.dataabilitydemo I 01100/My_log: UserDataAbility update value:1
01-01 10:21:54.741 26565-26565/com.example.dataabilitydemo I 01100/My_log: ProviderAbility query
01-01 10:21:54.743 26565-26565/com.example.dataabilitydemo I 01100/My_log: queryDataAbilitystart
01-01 10:21:54.744 26565-26565/com.example.dataabilitydemo I 01100/My_log: firstName=小精豆

最后,删除这条数据,DataAbility的delete()方法:

@Override
    public int delete(Uri uri, DataAbilityPredicates predicates) {
        if (ormContext == null) {
            HiLog.error(LABEL_LOG, "failed to delete, ormContext is null");
            return -1;
        }

        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
        int value = ormContext.delete(ormPredicates);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        return value;
    }

访问:

public void deleteDataAbility() throws DataAbilityRemoteException {
        DataAbilityHelper helper = DataAbilityHelper.creator(this);
        Uri uri = Uri.parse(uriString);
// 构造删除条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo("lastName", "史蒂夫");
        helper.delete(uri,predicates);
    }

增删改查就都写好了