diff --git a/documentation-website/Writerside/hi.tree b/documentation-website/Writerside/hi.tree index 2529375ba8..0e50ba64db 100644 --- a/documentation-website/Writerside/hi.tree +++ b/documentation-website/Writerside/hi.tree @@ -29,10 +29,9 @@ - + - diff --git a/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/CityEntity.kt b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/CityEntity.kt new file mode 100644 index 0000000000..80d291e22f --- /dev/null +++ b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/CityEntity.kt @@ -0,0 +1,12 @@ +package org.example.entities + +import org.example.tables.CitiesTable +import org.jetbrains.exposed.dao.ImmutableEntityClass +import org.jetbrains.exposed.dao.IntEntity +import org.jetbrains.exposed.dao.id.EntityID + +class CityEntity(id: EntityID) : IntEntity(id) { + val name by CitiesTable.name + + companion object : ImmutableEntityClass(CitiesTable) +} diff --git a/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/EntityWithUInt.kt b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/EntityWithUInt.kt new file mode 100644 index 0000000000..9c0aadae48 --- /dev/null +++ b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/EntityWithUInt.kt @@ -0,0 +1,16 @@ +package org.example.entities + +import org.jetbrains.exposed.dao.IntEntity +import org.jetbrains.exposed.dao.IntEntityClass +import org.jetbrains.exposed.dao.id.EntityID +import org.jetbrains.exposed.dao.id.IntIdTable + +object TableWithUnsignedInteger : IntIdTable() { + val uint = integer("uint") +} + +class EntityWithUInt(id: EntityID) : IntEntity(id) { + var uint: UInt by TableWithUnsignedInteger.uint.transform({ it.toInt() }, { it.toUInt() }) + + companion object : IntEntityClass(TableWithUnsignedInteger) +} diff --git a/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntity.kt b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntity.kt index c3f7ede64e..5d6331044f 100644 --- a/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntity.kt +++ b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntity.kt @@ -9,4 +9,5 @@ class UserEntity(id: EntityID) : IntEntity(id) { companion object : IntEntityClass(UsersTable) var name by UsersTable.name + var city by CityEntity referencedOn UsersTable.cityId } diff --git a/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntityWithOverride.kt b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntityWithOverride.kt new file mode 100644 index 0000000000..d3f3913bd5 --- /dev/null +++ b/documentation-website/Writerside/snippets/exposed-dao/src/main/kotlin/org/example/entities/UserEntityWithOverride.kt @@ -0,0 +1,18 @@ +package org.example.entities + +import org.example.tables.UsersTable +import org.jetbrains.exposed.dao.IntEntity +import org.jetbrains.exposed.dao.IntEntityClass +import org.jetbrains.exposed.dao.id.EntityID + +class UserEntityWithOverride(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(UsersTable) + + var name by UsersTable.name + var city by CityEntity referencedOn UsersTable.cityId + + override fun delete() { + println("Deleting user $name with ID: $id") + super.delete() + } +} diff --git a/documentation-website/Writerside/topics/DAO-Entity-definition.topic b/documentation-website/Writerside/topics/DAO-Entity-definition.topic index 0f699044c7..35000f4f7e 100644 --- a/documentation-website/Writerside/topics/DAO-Entity-definition.topic +++ b/documentation-website/Writerside/topics/DAO-Entity-definition.topic @@ -6,45 +6,234 @@ title="Entity definition" id="DAO-Entity-definition">

- Representing database tables as Kotlin objects ensures type safety and allows you to work with database - records just like regular Kotlin objects, taking full advantage of Kotlin's language features. + An Entity + in Exposed maps a database table record to a Kotlin object. This ensures type safety and allows you to work with + database records just like regular Kotlin objects, taking full advantage of Kotlin's language features.

- When using the DAO approach, IdTable needs to be associated with an Entity, because every database record + When using the DAO approach, IdTable needs to be associated with an Entity, + because every database record in this table needs to be mapped to an Entity instance, identified by its primary key.

-

- An entity instance is defined as a class. - In the following example, StarWarsFilmEntity is the entity class linked to the table StarWarsFilmsTable: -

- - - - - - - - - -
  • - Since StarWarsFilmsTable is an IntIdTable, the StarWarsFilmsEntity class extends from IntEntity, - which indicates that the id and primary key of StarWarsFilmsTable is of type Int. -
  • -
  • - The companion object block defines an EntityClass which is responsible for maintaining - the relation between the StarWarsFilmsEntity class and the actual table object, StarWarsFilmsTable. -
  • -
  • - Each column in the table is represented as a property in the class, where the by keyword - ensures the data is fetched or updated from the corresponding column when accessed. -
  • -
    -

    - Once the entity class is defined, instances of this class allow you to manipulate individual records - from the corresponding table. This could involve - creating a new record, - retrieving a row based on its primary key, - updating values, or - deleting records. -

    + +

    + You define an entity instance by creating a class. + In the following example, StarWarsFilmEntity is the entity class linked to the table + StarWarsFilmsTable: +

    + + + + + + + + + +

    + The entity type determines how the Entity class interacts with the table’s primary key. + Since StarWarsFilmsTable is an IntIdTable, the StarWarsFilmsEntity + class extends from IntEntity, + which indicates that the id and primary key of StarWarsFilmsTable is of type + Int. +

    +

    + The following entity types are supported: +

    + + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-int-entity/index.html"> + <code>IntEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of a wrapped Int + value. +

    +
    + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-long-entity/index.html"> + <code>LongEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of a wrapped Long + value. +

    +
    + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-u-int-entity/index.html"> + <code>UIntEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of a wrapped UInt + value. +

    +
    + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-u-long-entity/index.html"> + <code>ULongEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of a wrapped ULong + value. +

    +
    + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-u-u-i-d-entity/index.html"> + <code>UUIDEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of a wrapped UUID + value. +

    +
    + + + <a href="%BASE_API_URL%/exposed-dao/org.jetbrains.exposed.dao/-composite-entity/index.html"> + <code>CompositeEntity</code> + </a> + +

    + Base class for an entity instance identified by an id comprised of multiple wrapped values. +

    +
    +
    +
    + +

    + The EntityClass + in the companion object block is responsible for managing Entity instances, + such as creating, querying, and deleting records. It also maintains the relationship between the entity + class (StarWarsFilmEntity in this example) and the database table + (StarWarsFilmsTable). +

    +

    Each entity type is supported by a corresponding EntityClass, which accepts the following + parameters:

    + + + The IdTable containing rows mapped to entities managed by this class. + + + (Optional) The expected type of the Entity class. This can be omitted if it is the + class of the type argument provided to this EntityClass instance. + + + (Optional) The function that instantiates an Entity using the provided EntityID. + If not provided, reflection is used to determine the primary constructor on the first access + (which may affect performance). + + +

    + In the example above, IntEntityClass is specified in the companion object: +

    + +

    + This setup enables you to use functions provided by IntEntityClass to manage instances + of StarWarsFilmEntity effectively. +

    +
    + +

    + Each column in the table is represented as a property in the entity class, where the by + keyword ensures the data is fetched or updated from the corresponding column when accessed. +

    + +
    +

    + Once the entity class is defined, instances of this class allow you to manipulate individual records + from the corresponding table. This could involve + creating a new record, + retrieving a row based on its primary key, + updating values, or + deleting records. +

    +
    + +

    + For defining entities that are immutable, Exposed provides the additional + ImmutableEntityClass + and + ImmutableCachedEntityClass + . +

    +

    + The ImmutableCachedEntityClass uses an internal cache to store entity loading + states by the associated database. This ensures that entity updates are synchronized with this class as + the lock object. +

    +

    + To create an immutable entity, use either ImmutableEntityClass or + ImmutableCachedEntityClass as a companion object in your entity class. For example, here’s how + to define a CityEntity class: +

    + + +
  • + Properties are defined using val instead of var. This enforces immutability, + as val properties cannot be reassigned after initial assignment. +
  • +
  • + The primary function of the entity class in this context is to query data from the associated table, + not to modify it. Therefore, inserts can only be performed using the + DSL insert() method and updates + can be done either through the DSL update() + or the + ImmutableEntityClass.forceUpdateEntity() methods. +
  • +
    +
    + +

    + You can use override methods in both the Entity class and the EntityClass + companion object to extend functionality or manage entity behavior. +

    +

    + For example, here’s how to override the delete() method in a User entity: +

    + +

    + In this example, a custom message is printed before the delete() function of the superclass + (IntEntity) completes the deletion. +

    +
    + +

    + As databases typically store only basic types, such as integers and strings, it's not always convenient to keep + the same simplicity on Data Access Object (DAO) level. +

    +

    + For example, you might need to parse JSON from a VARCHAR column, or retrieve values from a cache + based on data from the database. + In such cases, the preferred approach is to use column transformations. +

    + +

    + Suppose that you want to define an unsigned integer field on an entity, but Exposed doesn't have such + column type yet. You can achieve this by using the following implementation: +

    + +

    + The transform function accept two lambdas that convert values to and from the original column type. + In this case, you make sure to store only UInt instances in the uint field. +

    +

    + Although it is still possible to insert or update values with negative integers via DAO, this approach assures + a cleaner business logic. +

    + + Note that these transformations will occur with every access to a field. Therefore, to maintain performance + efficiency, it is advisable to avoid heavy transformations in this context. + +
    +
    diff --git a/documentation-website/Writerside/topics/DAO-Field-Transformations.topic b/documentation-website/Writerside/topics/DAO-Field-Transformations.topic deleted file mode 100644 index ee4bd892d8..0000000000 --- a/documentation-website/Writerside/topics/DAO-Field-Transformations.topic +++ /dev/null @@ -1,46 +0,0 @@ - - - - -

    - As databases typically store only basic types, such as integers and strings, it's not always convenient to keep - the same simplicity on Data Access Object (DAO) level. -

    -

    - For example, you might need to parse JSON from a VARCHAR column, or retrieve values from a cache - based on data from the database. - In such cases, the preferred approach is to use column transformations. -

    - -

    - Suppose that you want to define an unsigned integer field on an entity, but Exposed doesn't have such - column type yet. You can achieve this by using the following implementation: -

    - () - } - ]]> -

    - The transform function accept two lambdas that convert values to and from the original column type. - In this case, you make sure to store only UInt instances in the uint field. -

    -

    - Although it is still possible to insert or update values with negative integers via DAO, this approach assures - a cleaner business logic. -

    - - Note that these transformations will occur with every access to a field. Therefore, to maintain performance - efficiency, it is advisable to avoid heavy transformations in this context. - -
    - -
    diff --git a/documentation-website/Writerside/v.list b/documentation-website/Writerside/v.list index c5cfcffbf2..eda9892e83 100644 --- a/documentation-website/Writerside/v.list +++ b/documentation-website/Writerside/v.list @@ -4,4 +4,5 @@ +