Skip to content
This repository has been archived by the owner on Mar 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #210 from Z-Jais/master
Browse files Browse the repository at this point in the history
Optimize entity loading and manage session interactions
  • Loading branch information
Ziedelth authored Nov 20, 2023
2 parents 71731f6 + b974209 commit c61b570
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 15 deletions.
6 changes: 3 additions & 3 deletions src/main/kotlin/fr/ziedelth/entities/Anime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ class Anime(
val image: String? = null,
@Column(nullable = true, columnDefinition = "TEXT")
var description: String? = null,
@ElementCollection(fetch = FetchType.EAGER)
@ElementCollection
@CollectionTable(
name = "anime_hash",
joinColumns = [JoinColumn(name = "anime_uuid")],
foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (anime_uuid) REFERENCES anime (uuid) ON DELETE CASCADE")
)
val hashes: MutableSet<String> = mutableSetOf(),
@ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.PERSIST, CascadeType.MERGE])
@ManyToMany(fetch = FetchType.LAZY, cascade = [CascadeType.PERSIST, CascadeType.MERGE])
@JoinTable(
name = "anime_genre",
joinColumns = [
Expand All @@ -63,7 +63,7 @@ class Anime(
]
)
val genres: MutableSet<Genre> = mutableSetOf(),
@ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.PERSIST, CascadeType.MERGE])
@ManyToMany(fetch = FetchType.LAZY, cascade = [CascadeType.PERSIST, CascadeType.MERGE])
@JoinTable(
name = "anime_simulcast",
joinColumns = [
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/fr/ziedelth/entities/Profile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class Profile(
val creationDate: String = Calendar.getInstance().toISO8601(),
@Column(nullable = false)
var lastUpdate: String = Calendar.getInstance().toISO8601(),
@OneToMany(fetch = FetchType.EAGER, cascade = [CascadeType.ALL], orphanRemoval = true, mappedBy = "profile")
@OneToMany(fetch = FetchType.LAZY, cascade = [CascadeType.ALL], orphanRemoval = true, mappedBy = "profile")
@OrderBy("add_date")
val animes: MutableSet<ProfileAnime> = mutableSetOf(),
@OneToMany(fetch = FetchType.EAGER, cascade = [CascadeType.ALL], orphanRemoval = true, mappedBy = "profile")
@OneToMany(fetch = FetchType.LAZY, cascade = [CascadeType.ALL], orphanRemoval = true, mappedBy = "profile")
@OrderBy("add_date")
val episodes: MutableSet<ProfileEpisode> = mutableSetOf(),
) : Serializable
18 changes: 12 additions & 6 deletions src/main/kotlin/fr/ziedelth/repositories/AbstractRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ open class AbstractRepository<T> {
private val entityName: String = entityClass.simpleName

fun find(uuid: UUID): T? {
return database.inReadOnlyTransaction { it.find(entityClass, uuid) }
return database.inReadOnlyTransaction { database.fullInitialize(it.find(entityClass, uuid)) }
}

fun exists(field: String, value: Any?): Boolean {
Expand All @@ -28,21 +28,23 @@ open class AbstractRepository<T> {

fun findAll(uuids: Collection<UUID>): List<T> {
return database.inReadOnlyTransaction {
it.createQuery("FROM $entityName WHERE uuid IN :uuids", entityClass)
database.fullInitialize(
it.createQuery("FROM $entityName WHERE uuid IN :uuids", entityClass)
.setParameter("uuids", uuids)
.resultList
.resultList
)
}
}

fun getAll(): MutableList<T> {
return database.inReadOnlyTransaction { it.createQuery("FROM $entityName", entityClass).resultList }
return database.inReadOnlyTransaction { database.fullInitialize(it.createQuery("FROM $entityName", entityClass).resultList) }
}

fun getAllBy(field: String, value: Any?): MutableList<T> {
return database.inReadOnlyTransaction {
val query = it.createQuery("FROM $entityName WHERE $field = :value", entityClass)
query.setParameter("value", value)
query.resultList
database.fullInitialize(query.resultList)
}
}

Expand Down Expand Up @@ -74,6 +76,10 @@ open class AbstractRepository<T> {
}
}

fun merge(entity: T): T {
return database.inTransaction { it.merge(entity) }
}

fun <A> getByPage(
clazz: Class<A>,
page: Int,
Expand All @@ -86,7 +92,7 @@ open class AbstractRepository<T> {
pair.forEach { param -> if (param != null) query.setParameter(param.first, param.second) }
query.firstResult = (limit * page) - limit
query.maxResults = limit
query.list()
database.fullInitialize(query.resultList)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class AnimeRepository : AbstractRepository<Anime>() {
Episode::class.java
)
query.setParameter("tag", tag)
val list = query.list()
val list = database.fullInitialize(query.resultList)

list.filter {
OffsetDateTime.parse(
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/fr/ziedelth/repositories/ProfileRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ProfileRepository : AbstractRepository<Profile>() {
return database.inReadOnlyTransaction {
val query = it.createQuery("FROM Profile WHERE tokenUuid = :value", Profile::class.java)
query.setParameter("value", value)
query.uniqueResult()
database.fullInitialize(query.uniqueResult())
}
}

Expand Down Expand Up @@ -77,7 +77,7 @@ class ProfileRepository : AbstractRepository<Profile>() {
if (anime != null && addAnimeToProfile(UUID.fromString(anime), profile)) return null
if (episode != null && addEpisodeToProfile(UUID.fromString(episode), profile)) return null
profile.lastUpdate = Calendar.getInstance().toISO8601()
return save(profile)
return merge(profile)
}

private fun removeAnimeToProfile(anime: UUID, loggedInProfile: Profile): Boolean {
Expand Down Expand Up @@ -108,7 +108,7 @@ class ProfileRepository : AbstractRepository<Profile>() {
if (anime != null && removeAnimeToProfile(UUID.fromString(anime), profile)) return null
if (episode != null && removeEpisodeToProfile(UUID.fromString(episode), profile)) return null
profile.lastUpdate = Calendar.getInstance().toISO8601()
return save(profile)
return merge(profile)
}

/**
Expand Down
31 changes: 31 additions & 0 deletions src/main/kotlin/fr/ziedelth/utils/Database.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package fr.ziedelth.utils

import jakarta.persistence.Entity
import org.hibernate.Hibernate
import org.hibernate.Session
import org.hibernate.SessionFactory
import org.hibernate.boot.registry.StandardServiceRegistryBuilder
Expand Down Expand Up @@ -65,6 +67,35 @@ open class Database {
return session
}

fun <T> fullInitialize(entity: T, hashes: MutableSet<Int> = mutableSetOf()): T {
if (entity == null || hashes.contains(entity.hashCode())) {
return entity
}

if (entity is Collection<*>) {
entity.forEach { fullInitialize(it, hashes) }
return entity
}

entity.let { ent ->
ent::class.java.declaredFields.forEach {
if (it.type == Set::class.java) {
it.isAccessible = true
val value = it[ent] ?: return@forEach
Hibernate.initialize(value)
hashes.add(value.hashCode())
fullInitialize(value, hashes)
} else if (it.type.isAnnotationPresent(Entity::class.java)) {
it.isAccessible = true
val value = it[ent] ?: return@forEach
fullInitialize(value, hashes)
}
}
}

return entity
}

fun <T> inTransaction(block: (Session) -> T): T {
getCurrentSession().use { session ->
val transaction = session.beginTransaction()
Expand Down

0 comments on commit c61b570

Please sign in to comment.