summaryrefslogtreecommitdiffstats
path: root/documentation/sqlcontainer/sqlcontainer-editing.asciidoc
blob: 9fe8d7ba7ad31d065354d83818bf91e1b467e36d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
---
title: Editing
order: 4
layout: page
---

[[sqlcontainer.editing]]
= Editing

Editing the items ( [classname]#RowItem#s) of SQLContainer can be done similarly
to editing the items of any Vaadin container. [classname]#ColumnProperties# of a
[classname]#RowItem# will automatically notify SQLContainer to make sure that
changes to the items are recorded and will be applied to the database
immediately or on commit, depending on the state of the auto-commit mode.

[[sqlcontainer.editing.adding]]
== Adding items

Adding items to an [classname]#SQLContainer# object can only be done via the
[methodname]#addItem()# method. This method will create a new [classname]#Item#
based on the connected database table column properties. The new item will
either be buffered by the container or committed to the database through the
query delegate depending on whether the auto commit mode (see the next section)
has been enabled.

When an item is added to the container it is impossible to precisely know what
the primary keys of the row will be, or will the row insertion succeed at all.
This is why the SQLContainer will assign an instance of
[classname]#TemporaryRowId# as a [classname]#RowId# for the new item. We will
later describe how to fetch the actual key after the row insertion has
succeeded.

If auto-commit mode is enabled in the [classname]#SQLContainer#, the
[methodname]#addItem()# method will return the final [classname]#RowId# of the
new item.


[[sqlcontainer.editing.fetching]]
== Fetching generated row keys

Since it is a common need to fetch the generated key of a row right after
insertion, a listener/notifier has been added into the
[classname]#QueryDelegate# interface. Currently only the [classname]#TableQuery#
class implements the [classname]#RowIdChangeNotifier# interface, and thus can
notify interested objects of changed row IDs. The events fill be fired after
[methodname]#commit()# in [classname]#TableQuery# has finished; this method is
called by [classname]#SQLContainer# when necessary.

To receive updates on the row IDs, you might use the following code (assuming
container is an instance of [classname]#SQLContainer#). Note that these events
are not fired if auto commit mode is enabled.


----
app.getDbHelp().getCityContainer().addListener(
    new QueryDelegate.RowIdChangeListener() {
        public void rowIdChange(RowIdChangeEvent event) {
            System.err.println("Old ID: " + event.getOldRowId());
            System.err.println("New ID: " + event.getNewRowId());
        }
    });
----


[[sqlcontainer.editing.version-column]]
== Version column requirement

If you are using the [classname]#TableQuery# class as the query delegate to the
[classname]#SQLContainer# and need to enable write support, there is an enforced
requirement of specifying a version column name to the [classname]#TableQuery#
instance. The column name can be set to the [classname]#TableQuery# using the
following statement:


----
tq.setVersionColumn("OPTLOCK");
----

The version column is preferrably an integer or timestamp typed column in the
table that is attached to the [classname]#TableQuery#. This column will be used
for optimistic locking; before a row modification the [classname]#TableQuery#
will check before that the version column value is the same as it was when the
data was read into the container. This should ensure that no one has modified
the row inbetween the current user's reads and writes.

Note! [classname]#TableQuery# assumes that the database will take care of
updating the version column by either using an actual [literal]#++VERSION++#
column (if supported by the database in question) or by a trigger or a similar
mechanism.

If you are certain that you do not need optimistic locking, but do want to
enable write support, you may point the version column to, for example, a
primary key column of the table.


[[sqlcontainer.editing.autocommit]]
== Auto-commit mode

[classname]#SQLContainer# is by default in transaction mode, which means that
actions that edit, add or remove items are recorded internally by the container.
These actions can be either committed to the database by calling
[methodname]#commit()# or discarded by calling [methodname]#rollback()#.

The container can also be set to auto-commit mode. When this mode is enabled,
all changes will be committed to the database immediately. To enable or disable
the auto-commit mode, call the following method:


----
public void setAutoCommit(boolean autoCommitEnabled)
----

It is recommended to leave the auto-commit mode disabled, as it ensures that the
changes can be rolled back if any problems are noticed within the container
items. Using the auto-commit mode will also lead to failure in item addition if
the database table contains non-nullable columns.


[[sqlcontainer.editing.modified-state]]
== Modified state

When used in the transaction mode it may be useful to determine whether the
contents of the [classname]#SQLContainer# have been modified or not. For this
purpose the container provides an [methodname]#isModified()# method, which will
tell the state of the container to the developer. This method will return true
if any items have been added to or removed from the container, as well as if any
value of an existing item has been modified.

Additionally, each [classname]#RowItem# and each [classname]#ColumnProperty#
have [methodname]#isModified()# methods to allow for a more detailed view over
the modification status. Do note that the modification statuses of
[classname]#RowItem# and [classname]#ColumnProperty# objects only depend on
whether or not the actual [classname]#Property# values have been modified. That
is, they do not reflect situations where the whole [classname]#RowItem# has been
marked for removal or has just been added to the container.