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.