Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: EXPOSED-159 Add KDocs for EntityClass reference functions #1848

Merged
merged 1 commit into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions documentation-website/Writerside/topics/Deep-Dive-into-DAO.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,33 +81,33 @@ movie.delete()
### many-to-one reference
Let's say you have this table:
```kotlin
object Users: IntIdTable() {
object Users : IntIdTable() {
val name = varchar("name", 50)
}
class User(id: EntityID<Int>): IntEntity(id) {
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
var name by Users.name
}
```
And now you want to add a table referencing this table (and other tables!):
```kotlin
object UserRatings: IntIdTable() {
object UserRatings : IntIdTable() {
val value = long("value")
val film = reference("film", StarWarsFilms)
val user = reference("user", Users)
}
class UserRating(id: EntityID<Int>): IntEntity(id) {
class UserRating(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<UserRating>(UserRatings)
var value by UserRatings.value
var film by StarWarsFilm referencedOn UserRatings.film // use referencedOn for normal references
var user by User referencedOn UserRatings.user
}
```
Now you can get the film for a rating in the same way you would get any other field:
Now you can get the film for a `UserRating` object, `filmRating`, in the same way you would get any other field:
```kotlin
filmRating.film // returns a StarWarsFilm object
```
Now if you wanted to get all the ratings for a film, you could do that by using the `FilmRating.find` function, but what is much easier is to just add a `referrersOn` field to the StarWarsFilm class:
Now if you wanted to get all the ratings for a film, you could do that by using the `filmRating.find` function, but it is much easier to just add a `referrersOn` field to the `StarWarsFilm` class:
```kotlin
class StarWarsFilm(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<StarWarsFilm>(StarWarsFilms)
Expand All @@ -116,10 +116,22 @@ class StarWarsFilm(id: EntityID<Int>) : IntEntity(id) {
...
}
```
You can call:
You can then access this field on a `StarWarsFilm` object, `movie`:
```kotlin
movie.ratings // returns all UserRating objects with this movie as film
```
Now imagine a scenario where a user only ever rates a single film. If you want to get the single rating for that user, you can add a `backReferencedOn` field to the `User` class to access the `UserRating` table data:
```kotlin
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
...
val rating by UserRating backReferencedOn UserRatings.user // make sure to use val and backReferencedOn
}
```
You can then access this field on a `User` object, `user1`:
```kotlin
user1.rating // returns a UserRating object
```
### Optional reference
You can also add an optional reference:
```kotlin
Expand All @@ -135,7 +147,7 @@ class UserRating(id: EntityID<Int>): IntEntity(id) {
...
}
```
Now `secondUser` will be a nullable field, and you should use `optionalReferrersOn` instead of `referrersOn` to get all the ratings for a `secondUser`.
Now `secondUser` will be a nullable field, and `optionalReferrersOn` should be used instead of `referrersOn` to get all the ratings for a `secondUser`.

```kotlin
class User(id: EntityID<Int>): IntEntity(id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,46 +294,138 @@ abstract class EntityClass<ID : Comparable<ID>, out T : Entity<ID>>(
private inline fun <reified R : Any> registerRefRule(column: Column<*>, ref: () -> R): R =
refDefinitions.getOrPut(column to R::class, ref) as R

/**
* Registers a reference as a field of the child entity class, which returns a parent object of this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using `reference()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Child
*/
infix fun <REF : Comparable<REF>> referencedOn(column: Column<REF>) = registerRefRule(column) { Reference(column, this) }

/**
* Registers an optional reference as a field of the child entity class, which returns a parent object of
* this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using either `optReference()` or
* `reference().nullable()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Post
*/
infix fun <REF : Comparable<REF>> optionalReferencedOn(column: Column<REF?>) = registerRefRule(column) { OptionalReference(column, this) }

/**
* Registers a reference as an immutable field of the parent entity class, which returns a child object of
* this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using `reference()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTestsData.YEntity
*/
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.backReferencedOn(
column: Column<REF>
):
ReadOnlyProperty<Entity<ID>, Target> = registerRefRule(column) { BackReference(column, this) }

/**
* Registers a reference as an immutable field of the parent entity class, which returns a child object of
* this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using `reference()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTestsData.YEntity
*/
@JvmName("backReferencedOnOpt")
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.backReferencedOn(
column: Column<REF?>
):
ReadOnlyProperty<Entity<ID>, Target> = registerRefRule(column) { BackReference(column, this) }

/**
* Registers an optional reference as an immutable field of the parent entity class, which returns a child object of
* this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using either `optReference()` or
* `reference().nullable()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Student
*/
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.optionalBackReferencedOn(
column: Column<REF>
) =
registerRefRule(column) { OptionalBackReference<TargetID, Target, ID, Entity<ID>, REF>(column as Column<REF?>, this) }

/**
* Registers an optional reference as an immutable field of the parent entity class, which returns a child object of
* this `EntityClass`.
*
* The reference should have been defined by the creation of a [column] using either `optReference()` or
* `reference().nullable()` on the child table.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Student
*/
@JvmName("optionalBackReferencedOnOpt")
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.optionalBackReferencedOn(
column: Column<REF?>
) =
registerRefRule(column) { OptionalBackReference<TargetID, Target, ID, Entity<ID>, REF>(column, this) }

/**
* Registers a reference as an immutable field of the parent entity class, which returns a collection of
* child objects of this `EntityClass` that all reference the parent.
*
* The reference should have been defined by the creation of a [column] using `reference()` on the child table.
*
* By default, this also stores the loaded entities to a cache.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityHookTestData.Country
*/
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.referrersOn(column: Column<REF>) =
registerRefRule(column) { Referrers<ID, Entity<ID>, TargetID, Target, REF>(column, this, true) }

/**
* Registers a reference as an immutable field of the parent entity class, which returns a collection of
* child objects of this `EntityClass` that all reference the parent.
*
* The reference should have been defined by the creation of a [column] using `reference()` on the child table.
*
* Set [cache] to `true` to also store the loaded entities to a cache.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.School
*/
fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.referrersOn(
column: Column<REF>,
cache: Boolean
) =
registerRefRule(column) { Referrers<ID, Entity<ID>, TargetID, Target, REF>(column, this, cache) }

/**
* Registers an optional reference as an immutable field of the parent entity class, which returns a collection of
* child objects of this `EntityClass` that all reference the parent.
*
* The reference should have been defined by the creation of a [column] using either `optReference()` or
* reference().nullable()` on the child table.
*
* By default, this also stores the loaded entities to a cache.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Category
*/
infix fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.optionalReferrersOn(
column: Column<REF?>
) =
registerRefRule(column) { OptionalReferrers<ID, Entity<ID>, TargetID, Target, REF>(column, this, true) }

/**
* Registers an optional reference as an immutable field of the parent entity class, which returns a collection of
* child objects of this `EntityClass` that all reference the parent.
*
* The reference should have been defined by the creation of a [column] using either `optReference()` or
* `reference().nullable()` on the child table.
*
* Set [cache] to `true` to also store the loaded entities to a cache.
*
* @sample org.jetbrains.exposed.sql.tests.shared.entities.EntityTests.Student
*/
fun <TargetID : Comparable<TargetID>, Target : Entity<TargetID>, REF : Comparable<REF>> EntityClass<TargetID, Target>.optionalReferrersOn(
column: Column<REF?>,
cache: Boolean = false
Expand Down
Loading