# 本地存储 - 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)
}
})
}
}
# 疯狂的矩形
举个例子,假设想储存在场景中一个矩形的位置。
这是示例的基础。 它包含一个名为crazy
的矩形,它是可拖动的,并将其当前的x
和y
位置显示成文本。
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数据库中。 为此,需要添加名为init
、read
和store
的数据库函数。 这些函数在组件完成和组件销毁时被调用。
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位置并将其应用于下一次运行应用程序。