1. Rich client
This artifact pulls in all required framework dependencies, except the ones related to database connectivity and logging, see below.
Client | Artifact |
---|---|
Swing |
is.codion:codion-swing-framework.ui:0.18.16 |
2. Database connectivity
A Codion client has three ways of connecting to a database, directly via a local JDBC connection or remotely via RMI or HTTP using the Codion remote server.
DB Connection | Artifact |
---|---|
Local |
is.codion:codion-framework-db-local:0.18.16 |
RMI |
is.codion:codion-framework-db-rmi:0.18.16 |
HTTP |
is.codion:codion-framework-db-http:0.18.16 |
2.1. DBMS
When connecting to the database with a local JDBC connection the DBMS module for the underlying database must be on the classpath. Note that these artifacts do not depend on the JDBC drivers, so those must be added separately.
The most used and tested DBMS modules are:
-
Oracle
-
PostgreSQL
-
H2 Database
DBMS | Artifact |
---|---|
Db2 |
is.codion:codion-dbms-db2:0.18.16 |
Derby |
is.codion:codion-dbms-derby:0.18.16 |
H2 |
is.codion:codion-dbms-h2:0.18.16 |
HSQL |
is.codion:codion-dbms-hsql:0.18.16 |
MariaDB |
is.codion:codion-dbms-mariadb:0.18.16 |
MySQL |
is.codion:codion-dbms-mysql:0.18.16 |
Oracle |
is.codion:codion-dbms-oracle:0.18.16 |
PostgreSQL |
is.codion:codion-dbms-postgresql:0.18.16 |
SQLite |
is.codion:codion-dbms-sqlite:0.18.16 |
SQL Server |
is.codion:codion-dbms-sqlserver:0.18.16 |
3. Logging
Codion uses SLF4J throughout so all you need to do is add a SLF4J bridge for your logging framework of choice to the classpath. If you use Logback, Log4J or Java Util Logging you can use one of the logging-proxy plugins below which will pull in the required dependencies and provide a main-menu action in the client for setting the logging level.
Logging | Artifact |
---|---|
Logback |
is.codion:codion-plugin-logback-proxy:0.18.16 |
Log4j |
is.codion:codion-plugin-log4j-proxy:0.18.16 |
Java Util Logging |
is.codion:codion-plugin-jul-proxy:0.18.16 |
4. Gradle
A minimal Gradle dependencies configuration for a Swing based client application, using the H2 database.
dependencies {
implementation "is.codion:codion-swing-framework-ui:0.18.16"
runtimeOnly "is.codion:codion-framework-db-local:0.18.16"
runtimeOnly "is.codion:codion-dbms-h2:0.18.16"
runtimeOnly "com.h2database:h2:2.3.230"
runtimeOnly "is.codion:codion-plugin-logback-proxy:0.18.16"
testImplementation "is.codion:codion-framework-domain-test:0.18.16"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.10.3"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.10.3"
}
5. Code examples
There are at minimum three steps involved in creating a Codion application:
-
Defining a domain model based on the underlying tables.
-
Creating edit panels for tables requiring CRUD functionality.
-
Assembling a client application from these building blocks.
5.1. Domain
Module |
Artifact |
is.codion.framework.domain |
is.codion:codion-framework-domain:0.18.16 |
5.1.1. Defining entities
The below examples are somewhat simplified, but functionally correct.
View example schema SQL
Note
|
Not all columns are used in the example code below. |
create user if not exists scott password 'tiger';
alter user scott admin true;
create schema store;
create table store.customer (
id varchar(36) not null,
first_name varchar(40) not null,
last_name varchar(40) not null,
email varchar(100),
active boolean default true not null,
constraint customer_pk primary key (id),
constraint customer_email_uk unique (email)
);
create table store.address (
id identity not null,
street varchar(120) not null,
city varchar(50) not null,
valid boolean default true not null,
constraint address_pk primary key (id),
constraint address_uk unique (street, city)
);
create table store.customer_address (
id identity not null,
customer_id varchar(36) not null,
address_id integer not null,
constraint customer_address_pk primary key (id),
constraint customer_address_uk unique (customer_id, address_id)
);
insert into store.customer(id, first_name, last_name, email)
values ('ff60ebc3-bae0-4c0f-b094-4129edd3665a', 'John', 'Doe', 'doe@doe.net');
insert into store.address(street, city)
values ('Elm Street 123', 'Syracuse');
insert into store.customer_address(customer_id, address_id)
values ('ff60ebc3-bae0-4c0f-b094-4129edd3665a', 1);
commit;
View full domain source
public static class Store extends DomainModel {
public static final DomainType DOMAIN = domainType(Store.class);
public Store() {
super(DOMAIN);
add(customer(), address(), customerAddress());
}
public interface Customer {
EntityType TYPE = DOMAIN.entityType("store.customer");
Column<String> ID = TYPE.stringColumn("id");
Column<String> FIRST_NAME = TYPE.stringColumn("first_name");
Column<String> LAST_NAME = TYPE.stringColumn("last_name");
}
EntityDefinition customer() {
return Customer.TYPE.define(
Customer.ID.define()
.primaryKey(),
Customer.FIRST_NAME.define()
.column()
.caption("First name")
.nullable(false)
.maximumLength(40),
Customer.LAST_NAME.define()
.column()
.caption("Last name")
.nullable(false)
.maximumLength(40))
.keyGenerator(new CustomerKeyGenerator())
.stringFactory(StringFactory.builder()
.value(Customer.LAST_NAME)
.text(", ")
.value(Customer.FIRST_NAME)
.build())
.build();
}
private static final class CustomerKeyGenerator implements KeyGenerator {
@Override
public void beforeInsert(Entity entity, DatabaseConnection connection) {
entity.put(Customer.ID, randomUUID().toString());
}
}
public interface Address {
EntityType TYPE = DOMAIN.entityType("store.address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> STREET = TYPE.stringColumn("street");
Column<String> CITY = TYPE.stringColumn("city");
}
EntityDefinition address() {
return Address.TYPE.define(
Address.ID.define()
.primaryKey(),
Address.STREET.define()
.column()
.caption("Street")
.nullable(false)
.maximumLength(120),
Address.CITY.define()
.column()
.caption("City")
.nullable(false)
.maximumLength(50))
.keyGenerator(automatic("store.address"))
.stringFactory(StringFactory.builder()
.value(Address.STREET)
.text(", ")
.value(Address.CITY)
.build())
.build();
}
public interface CustomerAddress {
EntityType TYPE = DOMAIN.entityType("store.customer_address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> CUSTOMER_ID = TYPE.stringColumn("customer_id");
Column<Integer> ADDRESS_ID = TYPE.integerColumn("address_id");
ForeignKey CUSTOMER_FK = TYPE.foreignKey("customer_fk", CUSTOMER_ID, Customer.ID);
ForeignKey ADDRESS_FK = TYPE.foreignKey("address_fk", ADDRESS_ID, Address.ID);
}
EntityDefinition customerAddress() {
return CustomerAddress.TYPE.define(
CustomerAddress.ID.define()
.primaryKey(),
CustomerAddress.CUSTOMER_ID.define()
.column()
.nullable(false),
CustomerAddress.CUSTOMER_FK.define()
.foreignKey()
.caption("Customer"),
CustomerAddress.ADDRESS_ID.define()
.column()
.nullable(false),
CustomerAddress.ADDRESS_FK.define()
.foreignKey()
.caption("Address"))
.keyGenerator(automatic("store.customer_address"))
.caption("Customer address")
.build();
}
}
To create a domain model we extend the DomainModel class and define a DomainType constant to identify the domain model.
In the constructor we call methods adding entity definitions to this domain model.
This class is continued below.
public static class Store extends DomainModel {
public static final DomainType DOMAIN = domainType(Store.class);
public Store() {
super(DOMAIN);
add(customer(), address(), customerAddress());
}
We create a namespace interface and define a EntityType constant based on the table and typed Column constants for each column, these constants specify the entity API, used when referring to the entity type or its columns.
In the associated method we create ColumnDefinition.Builder instances based on each Column, providing further configuration options, such as specifying a caption and maximum length, using methods in the Column class. We supply these ColumnDefinition.Builder instances to the EntityType.define() method, which returns a EntityDefinition.Builder instance, providing further configuration options for the entity definition, such as the key generation strategy. Finally, we add the definition builder to the domain model.
public interface Customer {
EntityType TYPE = DOMAIN.entityType("store.customer");
Column<String> ID = TYPE.stringColumn("id");
Column<String> FIRST_NAME = TYPE.stringColumn("first_name");
Column<String> LAST_NAME = TYPE.stringColumn("last_name");
}
EntityDefinition customer() {
return Customer.TYPE.define(
Customer.ID.define()
.primaryKey(),
Customer.FIRST_NAME.define()
.column()
.caption("First name")
.nullable(false)
.maximumLength(40),
Customer.LAST_NAME.define()
.column()
.caption("Last name")
.nullable(false)
.maximumLength(40))
.keyGenerator(new CustomerKeyGenerator())
.stringFactory(StringFactory.builder()
.value(Customer.LAST_NAME)
.text(", ")
.value(Customer.FIRST_NAME)
.build())
.build();
}
private static final class CustomerKeyGenerator implements KeyGenerator {
@Override
public void beforeInsert(Entity entity, DatabaseConnection connection) {
entity.put(Customer.ID, randomUUID().toString());
}
}
Next we define an entity based on the table store.address.
public interface Address {
EntityType TYPE = DOMAIN.entityType("store.address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> STREET = TYPE.stringColumn("street");
Column<String> CITY = TYPE.stringColumn("city");
}
EntityDefinition address() {
return Address.TYPE.define(
Address.ID.define()
.primaryKey(),
Address.STREET.define()
.column()
.caption("Street")
.nullable(false)
.maximumLength(120),
Address.CITY.define()
.column()
.caption("City")
.nullable(false)
.maximumLength(50))
.keyGenerator(automatic("store.address"))
.stringFactory(StringFactory.builder()
.value(Address.STREET)
.text(", ")
.value(Address.CITY)
.build())
.build();
}
And finally we define an entity based on the many-to-many relationship table store.customer_address, note the foreign keys.
public interface CustomerAddress {
EntityType TYPE = DOMAIN.entityType("store.customer_address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> CUSTOMER_ID = TYPE.stringColumn("customer_id");
Column<Integer> ADDRESS_ID = TYPE.integerColumn("address_id");
ForeignKey CUSTOMER_FK = TYPE.foreignKey("customer_fk", CUSTOMER_ID, Customer.ID);
ForeignKey ADDRESS_FK = TYPE.foreignKey("address_fk", ADDRESS_ID, Address.ID);
}
EntityDefinition customerAddress() {
return CustomerAddress.TYPE.define(
CustomerAddress.ID.define()
.primaryKey(),
CustomerAddress.CUSTOMER_ID.define()
.column()
.nullable(false),
CustomerAddress.CUSTOMER_FK.define()
.foreignKey()
.caption("Customer"),
CustomerAddress.ADDRESS_ID.define()
.column()
.nullable(false),
CustomerAddress.ADDRESS_FK.define()
.foreignKey()
.caption("Address"))
.keyGenerator(automatic("store.customer_address"))
.caption("Customer address")
.build();
}
5.2. UI
The EntityPanel class provides a Swing UI for viewing and editing entities. It is composed of a EntityEditPanel and a EntityTablePanel. For each of these panel classes there is a corresponding model class; SwingEntityModel, which is composed of a SwingEntityEditModel and a SwingEntityTableModel. The only class you are required to extend is the EntityEditPanel, which provides the input controls for editing an entity. Below we demonstrate how to set up a simple master/detail panel.
Module |
Artifact |
is.codion.swing.framework.ui |
is.codion:codion-swing-framework-ui:0.18.16 |
5.2.1. Master
Here we extend a EntityEditPanel to provide the UI for editing a customer and use that edit panel class when we assemble the EntityPanel. We use a default SwingEntityModel implementation, which internally, creates a default SwingEntityEditModel and SwingEntityTableModel.
class CustomerEditPanel extends EntityEditPanel {
public CustomerEditPanel(SwingEntityEditModel editModel) {
super(editModel);
}
@Override
protected void initializeUI() {
initialFocusAttribute().set(Customer.FIRST_NAME);
createTextField(Customer.FIRST_NAME);
createTextField(Customer.LAST_NAME);
addInputPanel(Customer.FIRST_NAME);
addInputPanel(Customer.LAST_NAME);
}
}
EntityConnectionProvider connectionProvider =
LocalEntityConnectionProvider.builder()
.domain(new Store())
.user(User.parse("scott:tiger"))
.build();
SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
EntityPanel customerPanel = new EntityPanel(customerModel,
new CustomerEditPanel(customerModel.editModel()));
5.2.2. Detail
Here we create a panel for viewing and editing customer addresses, much like the one above. We start by creating a default SwingEntityModel instance, which we add as a detail model on the customer model. Finally, we create a EntityPanel for the customer address and add that as a detail panel on the customer panel.
class CustomerAddressEditPanel extends EntityEditPanel {
public CustomerAddressEditPanel(SwingEntityEditModel editModel) {
super(editModel);
}
@Override
protected void initializeUI() {
initialFocusAttribute().set(CustomerAddress.CUSTOMER_FK);
createForeignKeyComboBox(CustomerAddress.CUSTOMER_FK);
createForeignKeyComboBox(CustomerAddress.ADDRESS_FK);
addInputPanel(CustomerAddress.CUSTOMER_FK);
addInputPanel(CustomerAddress.ADDRESS_FK);
}
}
SwingEntityModel customerAddressModel = new SwingEntityModel(CustomerAddress.TYPE, connectionProvider);
customerModel.addDetailModel(customerAddressModel);
EntityPanel customerAddressPanel = new EntityPanel(customerAddressModel,
new CustomerAddressEditPanel(customerAddressModel.editModel()));
customerPanel.addDetailPanel(customerAddressPanel);
//lazy initialization of UI components
customerPanel.initialize();
//populate the model with data from the database
customerModel.tableModel().refresh();
Dialogs.componentDialog(customerPanel)
.title("Customers")
.show();
5.3. Domain unit test
The DomainTest class provides a way to unit test the domain model. The test method performs insert, update, select and delete on a randomly generated entity instance and verifies the results.
Module |
Artifact |
is.codion.framework.domain.test |
is.codion:codion-framework-domain-test:0.18.16 |
class StoreTest extends DomainTest {
public StoreTest() {
super(new Store(), User.parse("scott:tiger"));
}
@Test
void customer() throws DatabaseException {
test(Customer.TYPE);
}
@Test
void address() throws DatabaseException {
test(Address.TYPE);
}
@Test
void customerAddress() throws DatabaseException {
test(CustomerAddress.TYPE);
}
}
5.4. Persistance
The EntityConnection interface provides select, insert, update, and delete methods. It has three available implementations, one of which is based on a local JDBC connection, used below.
Module |
Artifact |
Description |
is.codion.framework.db.core |
is.codion:codion-framework-db-core:0.18.16 |
Core database API |
is.codion.framework.db.local |
is.codion:codion-framework-db-local:0.18.16 |
Local JDBC implementation |
5.4.1. Selecting
Store domain = new Store();
EntityConnection connection =
LocalEntityConnection.localEntityConnection(
Database.instance(), domain, User.parse("scott:tiger"));
//select customer where last name = Doe
Entity johnDoe = connection.selectSingle(Customer.LAST_NAME.equalTo("Doe"));
//select all customer addresses
List<Entity> customerAddresses = //where customer = john doe
connection.select(CustomerAddress.CUSTOMER_FK.equalTo(johnDoe));
Entity customerAddress = customerAddresses.get(0);
Entity address = customerAddress.entity(CustomerAddress.ADDRESS_FK);
String lastName = johnDoe.get(Customer.LAST_NAME);
String street = address.get(Address.STREET);
String city = address.get(Address.CITY);
5.4.2. Persisting
Store domain = new Store();
EntityConnection connection =
LocalEntityConnection.localEntityConnection(
Database.instance(), domain, User.parse("scott:tiger"));
Entities entities = domain.entities();
Entity customer = entities.builder(Customer.TYPE)
.with(Customer.FIRST_NAME, "John")
.with(Customer.LAST_NAME, "Doe")
.build();
customer = connection.insertSelect(customer);
Entity address = entities.builder(Address.TYPE)
.with(Address.STREET, "Elm Street 321")
.with(Address.CITY, "Syracuse")
.build();
address = connection.insertSelect(address);
Entity customerAddress = entities.builder(CustomerAddress.TYPE)
.with(CustomerAddress.CUSTOMER_FK, customer)
.with(CustomerAddress.ADDRESS_FK, address)
.build();
customerAddress = connection.insertSelect(customerAddress);
customer.put(Customer.FIRST_NAME, "Jonathan");
connection.update(customer);
connection.delete(customerAddress.primaryKey());
Full code
/*
* This file is part of Codion.
*
* Codion is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Codion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Codion. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (c) 2004 - 2024, Björn Darri Sigurðsson.
*/
package is.codion.framework.demos.manual.quickstart;
import is.codion.common.db.connection.DatabaseConnection;
import is.codion.common.db.database.Database;
import is.codion.common.db.exception.DatabaseException;
import is.codion.common.user.User;
import is.codion.framework.db.EntityConnection;
import is.codion.framework.db.EntityConnectionProvider;
import is.codion.framework.db.local.LocalEntityConnection;
import is.codion.framework.db.local.LocalEntityConnectionProvider;
import is.codion.framework.domain.DomainModel;
import is.codion.framework.domain.DomainType;
import is.codion.framework.domain.entity.Entities;
import is.codion.framework.domain.entity.Entity;
import is.codion.framework.domain.entity.EntityDefinition;
import is.codion.framework.domain.entity.EntityType;
import is.codion.framework.domain.entity.KeyGenerator;
import is.codion.framework.domain.entity.StringFactory;
import is.codion.framework.domain.entity.attribute.Column;
import is.codion.framework.domain.entity.attribute.ForeignKey;
import is.codion.framework.domain.test.DomainTest;
import is.codion.swing.common.ui.dialog.Dialogs;
import is.codion.swing.framework.model.SwingEntityEditModel;
import is.codion.swing.framework.model.SwingEntityModel;
import is.codion.swing.framework.ui.EntityEditPanel;
import is.codion.swing.framework.ui.EntityPanel;
import org.junit.jupiter.api.Test;
import java.util.List;
import static is.codion.framework.demos.manual.quickstart.Example.Store.*;
import static is.codion.framework.domain.DomainType.domainType;
import static is.codion.framework.domain.entity.KeyGenerator.automatic;
import static java.util.UUID.randomUUID;
public final class Example {
public static class Store extends DomainModel {
public static final DomainType DOMAIN = domainType(Store.class);
public Store() {
super(DOMAIN);
add(customer(), address(), customerAddress());
}
public interface Customer {
EntityType TYPE = DOMAIN.entityType("store.customer");
Column<String> ID = TYPE.stringColumn("id");
Column<String> FIRST_NAME = TYPE.stringColumn("first_name");
Column<String> LAST_NAME = TYPE.stringColumn("last_name");
}
EntityDefinition customer() {
return Customer.TYPE.define(
Customer.ID.define()
.primaryKey(),
Customer.FIRST_NAME.define()
.column()
.caption("First name")
.nullable(false)
.maximumLength(40),
Customer.LAST_NAME.define()
.column()
.caption("Last name")
.nullable(false)
.maximumLength(40))
.keyGenerator(new CustomerKeyGenerator())
.stringFactory(StringFactory.builder()
.value(Customer.LAST_NAME)
.text(", ")
.value(Customer.FIRST_NAME)
.build())
.build();
}
private static final class CustomerKeyGenerator implements KeyGenerator {
@Override
public void beforeInsert(Entity entity, DatabaseConnection connection) {
entity.put(Customer.ID, randomUUID().toString());
}
}
public interface Address {
EntityType TYPE = DOMAIN.entityType("store.address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> STREET = TYPE.stringColumn("street");
Column<String> CITY = TYPE.stringColumn("city");
}
EntityDefinition address() {
return Address.TYPE.define(
Address.ID.define()
.primaryKey(),
Address.STREET.define()
.column()
.caption("Street")
.nullable(false)
.maximumLength(120),
Address.CITY.define()
.column()
.caption("City")
.nullable(false)
.maximumLength(50))
.keyGenerator(automatic("store.address"))
.stringFactory(StringFactory.builder()
.value(Address.STREET)
.text(", ")
.value(Address.CITY)
.build())
.build();
}
public interface CustomerAddress {
EntityType TYPE = DOMAIN.entityType("store.customer_address");
Column<Integer> ID = TYPE.integerColumn("id");
Column<String> CUSTOMER_ID = TYPE.stringColumn("customer_id");
Column<Integer> ADDRESS_ID = TYPE.integerColumn("address_id");
ForeignKey CUSTOMER_FK = TYPE.foreignKey("customer_fk", CUSTOMER_ID, Customer.ID);
ForeignKey ADDRESS_FK = TYPE.foreignKey("address_fk", ADDRESS_ID, Address.ID);
}
EntityDefinition customerAddress() {
return CustomerAddress.TYPE.define(
CustomerAddress.ID.define()
.primaryKey(),
CustomerAddress.CUSTOMER_ID.define()
.column()
.nullable(false),
CustomerAddress.CUSTOMER_FK.define()
.foreignKey()
.caption("Customer"),
CustomerAddress.ADDRESS_ID.define()
.column()
.nullable(false),
CustomerAddress.ADDRESS_FK.define()
.foreignKey()
.caption("Address"))
.keyGenerator(automatic("store.customer_address"))
.caption("Customer address")
.build();
}
}
static void customerPanel() {
class CustomerEditPanel extends EntityEditPanel {
public CustomerEditPanel(SwingEntityEditModel editModel) {
super(editModel);
}
@Override
protected void initializeUI() {
initialFocusAttribute().set(Customer.FIRST_NAME);
createTextField(Customer.FIRST_NAME);
createTextField(Customer.LAST_NAME);
addInputPanel(Customer.FIRST_NAME);
addInputPanel(Customer.LAST_NAME);
}
}
EntityConnectionProvider connectionProvider =
LocalEntityConnectionProvider.builder()
.domain(new Store())
.user(User.parse("scott:tiger"))
.build();
SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
EntityPanel customerPanel = new EntityPanel(customerModel,
new CustomerEditPanel(customerModel.editModel()));
class CustomerAddressEditPanel extends EntityEditPanel {
public CustomerAddressEditPanel(SwingEntityEditModel editModel) {
super(editModel);
}
@Override
protected void initializeUI() {
initialFocusAttribute().set(CustomerAddress.CUSTOMER_FK);
createForeignKeyComboBox(CustomerAddress.CUSTOMER_FK);
createForeignKeyComboBox(CustomerAddress.ADDRESS_FK);
addInputPanel(CustomerAddress.CUSTOMER_FK);
addInputPanel(CustomerAddress.ADDRESS_FK);
}
}
SwingEntityModel customerAddressModel = new SwingEntityModel(CustomerAddress.TYPE, connectionProvider);
customerModel.addDetailModel(customerAddressModel);
EntityPanel customerAddressPanel = new EntityPanel(customerAddressModel,
new CustomerAddressEditPanel(customerAddressModel.editModel()));
customerPanel.addDetailPanel(customerAddressPanel);
//lazy initialization of UI components
customerPanel.initialize();
//populate the model with data from the database
customerModel.tableModel().refresh();
Dialogs.componentDialog(customerPanel)
.title("Customers")
.show();
}
static void domainModelTest() {
class StoreTest extends DomainTest {
public StoreTest() {
super(new Store(), User.parse("scott:tiger"));
}
@Test
void customer() throws DatabaseException {
test(Customer.TYPE);
}
@Test
void address() throws DatabaseException {
test(Address.TYPE);
}
@Test
void customerAddress() throws DatabaseException {
test(CustomerAddress.TYPE);
}
}
}
static void selectEntities() throws DatabaseException {
Store domain = new Store();
EntityConnection connection =
LocalEntityConnection.localEntityConnection(
Database.instance(), domain, User.parse("scott:tiger"));
//select customer where last name = Doe
Entity johnDoe = connection.selectSingle(Customer.LAST_NAME.equalTo("Doe"));
//select all customer addresses
List<Entity> customerAddresses = //where customer = john doe
connection.select(CustomerAddress.CUSTOMER_FK.equalTo(johnDoe));
Entity customerAddress = customerAddresses.get(0);
Entity address = customerAddress.entity(CustomerAddress.ADDRESS_FK);
String lastName = johnDoe.get(Customer.LAST_NAME);
String street = address.get(Address.STREET);
String city = address.get(Address.CITY);
}
static void persistEntities() throws DatabaseException {
Store domain = new Store();
EntityConnection connection =
LocalEntityConnection.localEntityConnection(
Database.instance(), domain, User.parse("scott:tiger"));
Entities entities = domain.entities();
Entity customer = entities.builder(Customer.TYPE)
.with(Customer.FIRST_NAME, "John")
.with(Customer.LAST_NAME, "Doe")
.build();
customer = connection.insertSelect(customer);
Entity address = entities.builder(Address.TYPE)
.with(Address.STREET, "Elm Street 321")
.with(Address.CITY, "Syracuse")
.build();
address = connection.insertSelect(address);
Entity customerAddress = entities.builder(CustomerAddress.TYPE)
.with(CustomerAddress.CUSTOMER_FK, customer)
.with(CustomerAddress.ADDRESS_FK, address)
.build();
customerAddress = connection.insertSelect(customerAddress);
customer.put(Customer.FIRST_NAME, "Jonathan");
connection.update(customer);
connection.delete(customerAddress.primaryKey());
}
}