Data Domain
The Data Domain also called Domain Model or Problem Domain, is the set of classes that represent the data you want to persist; essentially the Java objects and their relationships that map to relational tables.
For mapping, EzQu works with Plain Old Java Objects (POJOs). It expects objects to follow the POJO / JavaBean pattern for CRUD, but it doesn't enforce encapsulation and can even use public fields. Note that EzQu accesses fields directly, bypassing getters and setters.
Types
EzQu manages three type categories, 'Java Types', 'Jdbc types' and 'Sql Types'. Developers mostly deal with java types, ezqu does the work of converting between the java types to the corresponding Sql Type, and matching these types to the specific database dialect used. For fine tuning EzQu lets developers specify an explicit SQL type or supply a custom Converter for type conversion. For example, usually the default mapping of String is varchar. The developer can choose to use CLOB instead.
Within the Java Types EzQU recognises two categories: Simple Types (also known as Value Types), which are mostly primitive wrappers, and Entity types, which are domain objects which have their own life cycle and usually are connected through relationships such as One2One, One2Many, Many2Many and Many2One.
Supported Database Dialects
EzQu supports a wide range of enterprise relational databases. You configure the dialect using the dialect attribute on the session factory. The supported dialects and their internal mapping classes are:
- H2 (Dialect key: 'H2' - Default)
- MySQL / MariaDB (Dialect key: 'MYSQL')
- Microsoft SQL Server (Dialect key: 'SQLSERVER')
- Oracle (Dialect key: 'ORACLE')
- PostgreSQL (Dialect key: 'POSTGRESQL')
- DB2 (Dialect key: 'DB2')
Simple Types
Following is a table showing the Simple Types supported by EzQu, their corresponding default Sql Types and DB types:
| Type | Default Type | Default Dialect Type |
|---|---|---|
| String | STRING | DB2, H2, MySql, MariaDB, postgresql - VARCHAR Oracle - VARCHAR2 |
| Boolean | BOOLEAN | DB2 - SMALLINT H2,postgresql - BOOLEAN MySql, MariaDB - TINYINT Oracle - NUMBER(1) MsSqlServer - BIT |
| Byte | BYTE | DB2 - SMALLINT H2, postgresql, MsSqlServer, MySql, MariaDB - TINYINT Oracle - NUMBER(3) |
| Integer | INTEGER | DB2, MySql, MariaDB, MsSqlServer, postgresql - INTEGER H2 - INT Oracle - NUMBER(10) |
| Double | DOUBLE | DB2, H2, MySql, MariaDB, MsSqlServer - DOUBLE Oracle - NUMBER(33,5) postgresql - FLOAT8 |
| Float | FLOAT | DB2, H2, MsSqlServer, postgresql - REAL MySql, MariaDB - FLOAT Oracle - NUMBER(33,5) |
| Long | LONG | DB2, H2, MySql, MariaDB, MsSqlServer, postgresql - BIGINT Oracle - Number(19) |
| Short | SHORT | DB2, H2, MySql, MariaDB, MsSqlServer, postgresql - SMALLINT Oracle - Number(5) |
| java.math.BigDecimal | BIGDECIMAL | DB2, MySql, MariaDB, MsSqlServer, postgresql - DECIMAL(38,15) H2 - NUMERIC(33,5) Oracle - NUMBER(38,15) |
| java.math.BigInteger | BIGINTEGER | DB2, MySql, MariaDB, MsSqlServer, postgresql - DECIMAL(65,0) H2 - NUMERIC(65,0) Oracle - NUMBER(38,0) |
| java.util.Date | UTIL_DATE | DB2, H2, postgresql - TIMESTAMP MySql, MariaDB, MsSqlServer - DATETIME Oracle - TIMESTAMP(6) |
| java.sql.Date | SQL_DATE | DATE |
| java.sql.Time | TIME | DB2, H2, MySql, MariaDB, MsSqlServer, postgresql - TIME Oracle - DATE |
| java.sql.Blob | BLOB | DB2, H2, MySql, MariaDB, Oracle - BLOB MsSqlServer - VARBINARY(MAX) postgresql - BINARY |
| java.sql.Clob | CLOB | DB2, H2, MySql, MariaDB, Oracle - CLOB MsSqlServer - VARCHAR(MAX) postgresql - TEXT |
| Timestamp | TIMESTAMP | DB2, H2, MySql, MariaDB, MsSqlServer, postgresql - TIMESTAMP Oracle - TIMESTAMP(9) |
| java.time.LocalDate | LOCALDATE | DATE |
| java.time.LocalDateTime | LOCALDATETIME | DB2, H2, postgresql - TIMESTAMP MySql, MariaDB, MsSqlServer - DATETIME Oracle - TIMESTAMP(6) |
| java.time.ZonedDateTime | ZONEDDATETIME | DB2, H2, postgresql - TIMESTAMP MySql, MariaDB, MsSqlServer - DATETIME Oracle - TIMESTAMP(6) |
| java.time.LocalTime | LOCALTIME | DB2, H2, MySql, MariaDB, MsSqlServer, postgresql - TIME Oracle - DATE |
| any enum type | ENUM ENUM_INT |
like String type. (The default behavior) like Integer type |
| java.util.UUID | UUID | DB2, H2, MySql, MariaDB, MsSqlServer - BINARY(16) postgresql - BYTEA Oracle - RAW(16) |
| java.net.INetAddress | INETADDRESS | DB2, H2, MySql, MariaDB, MsSqlServer - BINARY(16) postgresql - BYTEA Oracle - RAW(16) |
| any array '[]' type | ARRAY | DB2, MySql, MariaDB, Oracle - BLOB H2 - byte[] to BINARY, rest to ARRAY MsSqlServer - VARBINARY(MAX) postgresql - BINARY |
| any other Object implementing Serializable | NONE | DB2, H2, MySql, MariaDB, Oracle - BLOB MsSqlServer - VARBINARY(MAX) postgresql - BINARY |
EzQu does 'Simple Type' mapping automatically, unless you want to change the 'Default Type' to some other type. If so, you will need to use the @Column (more details here) annotation, which also lets you set constraints, length, precision, and of course a name, if the column name is different than the field name.
So you can do this:
/**
* @author centimia
*/
public class TestObject {
public Long id;
public String name;
public Boolean testResult;
public Double value;
public MyEnum anEnum;
}
or this, if you want to be more of a POJO:
/**
* @author centimia
*/
public class TestObject {
public Long id;
public String name;
public Boolean testResult;
public Double value;
public TestObject() {}
public TestObject(Long id, String name, Boolean testResult, Double value) {
super();
this.id = id;
this.name = name;
this.testResult = testResult;
this.value = value;
}
/**
* @return the id
*/
public Long getId() {
return this.id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return this.name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the testResult
*/
public Boolean getTestResult() {
return this.testResult;
}
/**
* @param testResult the testResult to set
*/
public void setTestResult(Boolean testResult) {
this.testResult = testResult;
}
/**
* @return the value
*/
public Double getValue() {
return this.value;
}
/**
* @param value the value to set
*/
public void setValue(Double value) {
this.value = value;
}
}
If EzQu was to create the table its psuedo code would look like this:
(Each database dialect does this a little different...)
CREATE IF NOT EXISTS TABLE TestObject(
id BIGINT,
name VARCHAR(256),
testResult BOOLEAN,
value DOUBLE,
anEnum VARCHAR(256)
)
One other thing to note here, EzQu maps using the exact field names. If your database is case-sensitive, that matters; otherwise the DB's own case handling is used, and EzQu will still match fields to columns nonetheless
Here is an example of a simple object which uses the @Column annotation. Note that it also can be a POJO
/**
* @author centimia
*/
public class TestObject {
@Column(unique=true)
public Long id;
@Column(name="FULL_NAME", length=20)
public String name;
@Column(name="TEST_RESULT")
public Boolean testResult;
@Column(length=15, precision=4)
public Double value;
@Column(name="AN_ENUM" notNull=true, type=Types.ENUM_INT)
public MyEnum anEnum;
}
So now the create would look like this:
CREATE IF NOT EXISTS TABLE TestObject(
id BIGINT UNIQUE,
FULL_NAME VARCHAR(20),
TEST_RESULT BOOLEAN,
value DOUBLE(15,4),
AN_ENUM INTEGER NOT NULL
)
Persisting such an object to the underlying db is simple. For an object setup with values such as:
TestObject tObject = new TestObject();
tObject.setId(1L);
tObject.setName("Wonderful Object");
tObject.setTestResult(Boolean.TRUE);
tObject.setValue(15.0);
tObject.setAnEnum(MyEnum.BLUE);
You will persist the object like this*
sessionFactory.runInSession(db -> {
try {
db.insert(tObject);
db.commit();
}
catch (Exception any) {
db.rollback();
}
});* Of course this depends on things like, where the transaction is handled, error handling and more. We get into all these things later.Critical Constraint for Arrays: You cannot use arrays to hold EzQu entities. If EzQu detects an array of objects annotated with @Entity or @MappedSuperclass, the framework will throw an IllegalArgumentException. You must use a Collection type (like List or Set) alongside relationship annotations (like @One2Many) to manage entity relationships.
Overriding Default Type Mappings
Sometimes, the default SQL type mapped by the dialect is not what you want. For instance, String defaults to VARCHAR, but if you are storing massive amounts of text, you likely need a CLOB (or TEXT depending on the dialect).
You can force EzQu to use a different SQL type by utilizing the @Column annotation and setting the type parameter.
import com.centimia.orm.ezqu.annotation.Column;
import com.centimia.orm.ezqu.annotation.Entity;
import java.sql.Types;
@Entity
public class Article {
// Forces EzQu to treat this String as a CLOB when creating the table
// and when reading/writing to the database.
@Column(type = Types.CLOB)
private String fullContent;
}
This grants developers fine-grained control over the generated schema without sacrificing the convenience of standard Java POJOs.