# 本地存储 - SQL

Qt Quick支持在Web浏览器中熟知的本地存储API,即本地存储API。 该API在import QtQuick.LocalStorage 2.0中提供。

通常,它将内容存储到SQLite数据库中,此数据库位于系统特定的、基于给定的数据库名称和版本的唯一ID的文件中。 无法列出或删除现有的数据库,但可以从QQmlEngine::offlineStoragePath()中找到存储的位置。

可以通过首先创建数据库对象然后在数据库上创建事务来使用API。 每个事务可以包含一个或多个SQL查询。 当事务内部的SQL查询失败时,事务将回滚。

例如,要从带有文本列的简单注释表中读取内容,可以像下面这样使用本地存储:

您可以通过首先创建数据库对象然后在数据库上创建事务来使用 API。 每个事务可以包含一个或多个SQL查询。 当事务内部的SQL查询失败时,事务将回滚。

import QtQuick
import QtQuick.LocalStorage 2.0

Item {
    Component.onCompleted: {
        const db = LocalStorage.openDatabaseSync("MyExample", "1.0", "Example database", 10000)
        db.transaction( function(tx) {
            const result = tx.executeSql('select * from notes')
            for(let i = 0; i < result.rows.length; i++) {
                print(result.rows[i].text)
            }
        })
    }
}

# 疯狂的矩形

举个例子,假设想储存在场景中一个矩形的位置。

image

这是示例的基础。 它包含一个名为crazy的矩形,它是可拖动的,并将其当前的xy位置显示成文本。

Item {
    width: 400
    height: 400

    Rectangle {
        id: crazy
        objectName: 'crazy'
        width: 100
        height: 100
        x: 50
        y: 50
        color: "#53d769"
        border.color: Qt.lighter(color, 1.1)
        Text {
            anchors.centerIn: parent
            text: Math.round(parent.x) + '/' + Math.round(parent.y)
        }
        MouseArea {
            anchors.fill: parent
            drag.target: parent
        }
    }
    // ...

矩形可以被随意拖动。 当关闭应用程序并再次启动它时,矩形位于相同的位置。

现在补充一点,矩形的x/y位置存储在SQL数据库中。 为此,需要添加名为initreadstore的数据库函数。 这些函数在组件完成和组件销毁时被调用。

import QtQuick
import QtQuick.LocalStorage 2.0

Item {
    // reference to the database object
    property var db

    function initDatabase() {
        // initialize the database object
    }

    function storeData() {
        // stores data to DB
    }

    function readData() {
        // reads and applies data from DB
    }

    Component.onCompleted: {
        initDatabase()
        readData()
    }

    Component.onDestruction: {
        storeData()
    }
}

还可以将数据库相关代码抽取到自己的JS库中,该库执行所有逻辑。 如果逻辑变得更加复杂的话,这将是首选方式。

在数据库初始化函数中,创建数据库对象并确保创建SQL表。 请注意,数据库功能使用非常方便,因此可以在控制台上进行操作。

function initDatabase() {
    // initialize the database object
    print('initDatabase()')
    db = LocalStorage.openDatabaseSync("CrazyBox", "1.0", "A box who remembers its position", 100000)
    db.transaction( function(tx) {
        print('... create table')
        tx.executeSql('CREATE TABLE IF NOT EXISTS data(name TEXT, value TEXT)')
    })
}

应用程序接下来调用read函数从数据库中读取现有数据。 这里需要区分表中是否已经存在数据。 为了检查,查看select子句返回了多少行。

function readData() {
    // reads and applies data from DB
    print('readData()')
    if(!db) { return }
    db.transaction(function(tx) {
        print('... read crazy object')
        const result = tx.executeSql('select * from data where name="crazy"')
        if(result.rows.length === 1) {
            print('... update crazy geometry')
            // get the value column
            const value = result.rows[0].value
            // convert to JS object
            const obj = JSON.parse(value)
            // apply to object
            crazy.x = obj.x
            crazy.y = obj.y
        }
    })
}

期望将数据存储在value列内包含的JSON字符串中。 这不是典型的SQL使用方式,但可以很好地与JS代码配合使用。 因此,没有将x、y作为属性存储在表中,而是使用JSON stringify/parse方法将它们存储为完整的JS对象。 最后,得到一个具有x和y属性的有效JS对象,可以将其应用于此疯狂矩形。

为了存储数据,需要区分更新和插入情况。 当记录已经存在时,使用更新,如果不存在名为“crazy”的记录,则使用插入。

function storeData() {
    // stores data to DB
    print('storeData()')
    if(!db) { return }
    db.transaction(function(tx) {
        print('... check if a crazy object exists')
        var result = tx.executeSql('SELECT * from data where name = "crazy"')
        // prepare object to be stored as JSON
        var obj = { x: crazy.x, y: crazy.y }
        if(result.rows.length === 1) { // use update
            print('... crazy exists, update it')
            result = tx.executeSql('UPDATE data set value=? where name="crazy"', [JSON.stringify(obj)])
        } else { // use insert
            print('... crazy does not exists, create it')
            result = tx.executeSql('INSERT INTO data VALUES (?,?)', ['crazy', JSON.stringify(obj)])
        }
    })
}

除了选取查询整个记录集,还可以使用SQLite计数函数,如下所示:SELECT COUNT(*) from data where name = "crazy",这将返回一行数据,这个数据表示使用受选择查询影响的行数。 另外,这是常用的SQL代码。 作为一个附加特性,在查询中使用了?与SQL值的绑定。

现在可以拖动矩形,当退出应用程序时,数据库会存储x/y位置并将其应用于下一次运行应用程序。

最后更新: 1/26/2022, 7:34:58 PM