blob: ad3c733e8628b170bc7e72a2a34e4d9427b54a71 [file] [log] [blame]
///////////////////////////////////////////////////////////////
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
///////////////////////////////////////////////////////////////
[[extension-es-sql,SQL EntityStore]]
= SQL EntityStore =
[devstatus]
--------------
source=extensions/entitystore-sql/dev-status.xml
--------------
This entitystore is backed by a SQL server, and maps each mixin type of the Composite into separate tables. This is more
enterprise-friendly, but comes at the cost of less performance compared to the <<extension-es-sqlkv>>.
This extension fully leverage the <<library-sql>> meaning that you must use it to assemble your DataSource and that you
get <<library-circuitbreaker,Circuit Breaker>> and <<library-jmx, JMX>> integration for free.
include::../../build/docs/buildinfo/artifact.txt[]
== Assembly ==
Assembly is done using the provided Assembler:
[snippet,java]
----
source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/SqlEntityStoreTest.java
tag=assembly
----
== Configuration ==
Here are the available configuration properties:
[snippet,java]
----
source=extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java
tag=config
----
All authentication related properties are optional.
By default no authentication is used.
As soon as you provide a `username`, authentication is set up.
It is also strongly recommended that a connection pool is setup. <<library-sql-dbcp>> and <<library-bonecp>> are
available in Polygene, but you can create your own.
== Table Layout ==
The SQL Entity Store will create, if createIfMissing() is true, or expect that the following tables exist.
[width="80%",options="header", cols="4*<", title="TYPES Table", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Java classname of the Entity Type.
|_table_name |VARCHAR ||Chosen name of the Mixin table. This name is the simple name of the class name, unless that table already exists, in which case a sequence number (starting with 0) is added at the end of the name, e.g. Person_0.
|_created_at |TIMESTAMP ||The time of the creation into this table.
|_modified_at |TIMESTAMP ||The time of the last modification of this record. Should never change.
|=======
Or in DDL (assuming default value for SqlEntityStoreConfiguration.typesTableName();
[source, bash]
----
create table if not exists "TYPES"(
"_identity" varchar null,
"_table_name" varchar null,
"_created_at" timestamp null,
"_modified_at" timestamp null,
primary key ("_identity")
)
----
[width="80%",options="header", cols="4*<", title="ENTITIES Table", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Identity of the entity.
|_created_at |TIMESTAMP ||The time of creation of the entity.
|_type |VARCHAR ||The identity of the type of entity. Linked to the TYPES table _identity field.
|_app_version |VARCHAR ||The Application.version() when the entity was last modified.
|_version |VARCHAR ||The MVCC version of the entity, to ensure consistency with optimistic locking.
|_modified_at |TIMESTAMP ||The time of latest change to the entity.
|_value_id |VARCHAR ||The identity of the values that are stored in the Mixin tables (their _identity field)
|=======
[source, bash]
----
create table if not exists "ENTITIES"(
"_identity" varchar null,
"_created_at" timestamp null,
"_type" varchar null,
"_app_version" varchar null,
"_version" varchar null,
"_modified_at" timestamp null,
"_value_id" varchar null,
primary key ("_identity")
)
----
Additionally, for each Mixin type, two tables will be created. One that contains one field per Property and
one field per Association. The second table will contain a fixed layout that holds all ManyAssociation and all
NamedAssociarion in a multi-field key-value table (see below).
The primary Mixin table will be named as the Mixin type's simple class name, unless there is conflicts, in which
case a sequence number will be added to the table name. The TYPES table contains the mapping from Mixin type
(i.e. Java class name) to table name.
For instance, the following types will end up creating 4 Mixin tables, plus the 4 association tables,
[snippet,java]
----
source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/DocSupport.java
tag=types
----
And the structures will be;
[width="80%",options="header", cols="4*<", title="Person", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Identity of the current value, i.e. _value_id from ENTITIES table
|_created_at |TIMESTAMP ||The time of creation of the entity value. It will become possible to choose to keep old values for history/audit purposes, but not yet supported. This field is preparation for that.
|spouse |VARCHAR ||Association<Person> spouse();
|=======
And the corresponding DDL.
[source, bash]
----
create table "Person" (
"_identity" varchar null,
"_created_at" timestamp null,
"spouse" varchar null,
primary key ("_identity")
)
----
[width="80%",options="header", cols="4*<", title="HasName", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Identity of the current value, i.e. _value_id from ENTITIES table
|_created_at |TIMESTAMP ||The time of creation of the entity value. It will become possible to choose to keep old values for history/audit purposes, but not yet supported. This field is preparation for that.
|name |VARCHAR ||Property<String> name();
|=======
And the corresponding DDL.
[source, bash]
----
create table "HasName" (
"_identity" varchar null,
"_created_at" timestamp null,
"name" varchar null,
primary key ("_identity")
)
----
[width="80%",options="header", cols="4*<", title="HasAddress", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Identity of the current value, i.e. _value_id from ENTITIES table
|_created_at |TIMESTAMP ||The time of creation of the entity value. It will become possible to choose to keep old values for history/audit purposes, but not yet supported. This field is preparation for that.
|street1 |VARCHAR ||Property<String> street1();
|street2 |VARCHAR ||Property<String> street2();
|zipCode |VARCHAR ||Property<String> zipCode();
|country |VARCHAR ||Assocication<String> country(); which contains Identity of the Country entity referenced.
|=======
And the corresponding DDL.
[source, bash]
----
create table "HasName" (
"_identity" varchar null,
"_created_at" timestamp null,
"street1" varchar null,
"street2" varchar null,
"zipCode" varchar null,
"country" varchar null,
primary key ("_identity")
)
----
[width="80%",options="header", cols="4*<", title="Country", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR |PRIMARY KEY |The Identity of the current value, i.e. _value_id from ENTITIES table
|_created_at |TIMESTAMP ||The time of creation of the entity value. It will become possible to choose to keep old values for history/audit purposes, but not yet supported. This field is preparation for that.
|=======
And the corresponding DDL.
[source, bash]
----
create table "HasName" (
"_identity" varchar null,
"_created_at" timestamp null,
primary key ("_identity")
)
----
NOTE: Country has no fields, as the HasName mixin type will be in its own table (above). But the _created_at field,
indicating latest change time, will be maintained.
And additionally four tables will be created, with identical structures. The names will be
Person_ASSOCS, HasName_ASSOCS, HasAddress_ASSOCS, Country_ASSOCS and the structure is;
[width="80%",options="header", cols="4*<", title="*_ASSOCS", halign="left"]
|=======
|*Field* |*Type* |*Constraint* |*Description*
|_identity |VARCHAR ||The Identity of the current value, i.e. _value_id from ENTITIES table
|_created_at |TIMESTAMP ||The time of creation of the entity value. It will become possible to choose to keep old values for history/audit purposes, but not yet supported. This field is preparation for that.
|_name |VARCHAR ||The name of the ManyAssociation or NamedAssociation in the Mixin type.
|_index |VARCHAR ||For NamedAssociations this is the name of the association, i.e. the key. For ManyAssociation, this is the sequence number within the ordered list.
|_reference |VARCHAR ||The entity identity that the association is pointing to.
|=======
[source, bash]
----
create table if not exists "Person_ASSOCS"(
"_identity" varchar null,
"_created_at" timestamp null,
"_name" varchar null,
"_index" varchar null,
"_reference" varchar null
)
----
Additionally, one INDEX will be created for each _ASSOCS table. So the above four will have
[source, bash]
----
create index "IDX_Person_ASSOCS" on "Person_ASSOCS"("_identity")
create index "IDX_HasName_ASSOCS" on "HasName_ASSOCS"("_identity")
create index "IDX_HasAddress_ASSOCS" on "HasAddress_ASSOCS"("_identity")
create index "IDX_Country_ASSOCS" on "Country_ASSOCS"("_identity")
----