Module org.panteleyev.persistence

Persistence library provides annotation classes for database access.

Database

Database manipulation is beyond the scope of this API. Calling code must supply correct DataSource and ensure database does exist and proper access control is established.

Table

Class implementing database table is defined by the annotation Table. Such class must also implement interface Record.

API currently supports the following primary key types:

In case of Integer one may use DAO.generatePrimaryKey(java.lang.Class<? extends org.panteleyev.persistence.Record<K>>) to generate unique values for the appropriate table classes. Also make sure that application calls DAO.preload(java.util.Collection<java.lang.Class<? extends org.panteleyev.persistence.Record>>) first.

Deserialization

API supports two ways of object deserialization: by constructor and direct field assignment. Constructor must be used for objects with final fields or in case of additional initialization.

Field Assignment

There must be no-argument constructor, either default or explicit. Setters are not used, i.e. there is no way to define additional deserialization logic in case of field assignment.


@Table("book")
class Book implements Record {
    @PrimaryKey
    @Column(Column.ID)
    private int id;
    @Column("title")
    private String title;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
 

Constructor

Constructor deserialization is triggered by RecordBuilder as shown below. Such constructor must have parameters corresponding to table columns.


@Table("book")
class Book implements Record {
    @PrimaryKey
    @Column(Field.ID)
    private final int id;
    @Column("title")
    private final String title;

    @RecordBuilder
    public Book (@Column(Column.ID) int id, @Column("title") String title) {
        this.id = id;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public String getTitle() {
        return title
    }
}
 

Data Types

The following data types are supported:

Data Types
JavaSQLiteMySQLComment
int
Integer
INTEGERINTEGER
long
Long
INTEGERBIGINT
boolean
Boolean
BOOLEANBOOLEAN
String VARCHAR ( Column.length() ) VARCHAR ( Column.length() )
String with Column.isJson() = true BLOB JSON
BigDecimal VARCHAR ( Column.precision() + 1 ) DECIMAL ( Column.precision(), Column.scale() ) MySQL representation does not guarantee that retrieved value will be equal to original one by means of Object.equals(java.lang.Object). Use BigDecimal.compareTo(java.math.BigDecimal) instead.
Date INTEGER BIGINT Dates are stored as long using Date.getTime()
LocalDate INTEGER BIGINT Local dates are stored as long using LocalDate.toEpochDay()
byte[] BLOB VARBINARY ( Column.length() )
UUID VARCHAR(36) BINARY(16) For MySQL the following conversion functions are used between string and binary representation: BIN_TO_UUID() and UUID_TO_BIN()

Indexes and Foreign Keys


@Table("parent_table")
public class ParentTable implements Record {
    @Column("data")
    @Index(value = "data", unique = true)
    private String data;

    public String getData() {
        return data;
    }
}
 

This will produce the following SQL for indexed field:
CREATE UNIQUE INDEX data ON parent_table(data)


@Table("child_table")
public class ChildTable implements Record {
    @Column("parent_data")
    @ForeignKey(table = ParentTable.class, field = "data",
        onDelete = ReferenceOption.RESTRICT, onUpdate = ReferenceOption.CASCADE)
    private final String parentData;

    public String getParentData() {
        return parentData;
    }
}
 

This will produce the following SQL for the foreign key:
CREATE FOREIGN KEY(parent_data) REFERENCES parent_table(data) ON DELETE RESTRICT ON UPDATE CASCADE

See Also:
MySQL Data Types