diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt index d792505fa0..3da119fba0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt @@ -3,6 +3,7 @@ package io.tolgee.activity import io.tolgee.activity.data.ActivityType import io.tolgee.activity.projectActivityView.ProjectActivityViewByPageableProvider import io.tolgee.activity.projectActivityView.ProjectActivityViewByRevisionProvider +import io.tolgee.component.CurrentDateProvider import io.tolgee.dtos.query_results.TranslationHistoryView import io.tolgee.events.OnProjectActivityStoredEvent import io.tolgee.model.activity.ActivityModifiedEntity @@ -10,10 +11,10 @@ import io.tolgee.model.activity.ActivityRevision import io.tolgee.model.views.activity.ProjectActivityView import io.tolgee.repository.activity.ActivityModifiedEntityRepository import io.tolgee.util.Logging +import io.tolgee.util.doInStatelessSession import io.tolgee.util.flushAndClear -import io.tolgee.util.logger -import jakarta.persistence.EntityExistsException import jakarta.persistence.EntityManager +import org.hibernate.StatelessSession import org.springframework.context.ApplicationContext import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable @@ -24,50 +25,45 @@ import org.springframework.transaction.annotation.Transactional class ActivityService( private val entityManager: EntityManager, private val applicationContext: ApplicationContext, - private val activityModifiedEntityRepository: ActivityModifiedEntityRepository + private val activityModifiedEntityRepository: ActivityModifiedEntityRepository, + private val currentDateProvider: CurrentDateProvider ) : Logging { @Transactional fun storeActivityData(activityRevision: ActivityRevision, modifiedEntities: ModifiedEntitiesType) { // let's keep the persistent context small entityManager.flushAndClear() - val mergedActivityRevision = activityRevision.persist() - mergedActivityRevision.persistedDescribingRelations() - - mergedActivityRevision.modifiedEntities = modifiedEntities.persist() - - entityManager.flushAndClear() - + val mergedActivityRevision = entityManager.doInStatelessSession { statelessSession -> + val mergedActivityRevision = statelessSession.persist(activityRevision) + statelessSession.persistedDescribingRelations(mergedActivityRevision) + mergedActivityRevision.modifiedEntities = statelessSession.persist(modifiedEntities) + mergedActivityRevision + } applicationContext.publishEvent(OnProjectActivityStoredEvent(this, mergedActivityRevision)) - - entityManager.flushAndClear() } - private fun ModifiedEntitiesType.persist(): MutableList { - val list = this.values.flatMap { it.values }.toMutableList() + private fun StatelessSession.persist(modifiedEntities: ModifiedEntitiesType): MutableList { + val list = modifiedEntities.values.flatMap { it.values }.toMutableList() list.forEach { activityModifiedEntity -> - try { - entityManager.persist(activityModifiedEntity) - } catch (e: EntityExistsException) { - logger.debug("ModifiedEntity entity already exists in persistence context, skipping", e) - } + this.insert(activityModifiedEntity) } return list } - private fun ActivityRevision.persistedDescribingRelations() { + private fun StatelessSession.persistedDescribingRelations(activityRevision: ActivityRevision) { @Suppress("UselessCallOnCollection") - describingRelations.filterNotNull().forEach { - entityManager.persist(it) + activityRevision.describingRelations.filterNotNull().forEach { + this.insert(it) } } - private fun ActivityRevision.persist(): ActivityRevision { - return if (id == 0L) { - entityManager.persist(this) - this + private fun StatelessSession.persist(activityRevision: ActivityRevision): ActivityRevision { + return if (activityRevision.id == 0L) { + activityRevision.timestamp = currentDateProvider.date + this.insert(activityRevision) + activityRevision } else { - entityManager.getReference(ActivityRevision::class.java, id) + entityManager.getReference(ActivityRevision::class.java, activityRevision.id) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/HibernateSession.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/HibernateSession.kt deleted file mode 100644 index 16607834e3..0000000000 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/HibernateSession.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.tolgee.configuration - -// -// @Configuration -// class HibernateSessionConfiguration( -// private val dataSource: DataSource -// ) { -// @Bean -// fun sessionFactory(emf: EntityManagerFactory?): LocalSessionFactoryBean { -// val sessionFactory = LocalSessionFactoryBean() -// sessionFactory.setDataSource(dataSource) -// sessionFactory.setPackagesToScan("io.tolgee.model") -// sessionFactory.hibernateProperties = hibernateProperties() -// return sessionFactory -// } -// } diff --git a/backend/data/src/main/kotlin/io/tolgee/util/entityManagerExt.kt b/backend/data/src/main/kotlin/io/tolgee/util/entityManagerExt.kt index bc55bd8855..859a4a0cbc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/entityManagerExt.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/entityManagerExt.kt @@ -2,6 +2,7 @@ package io.tolgee.util import jakarta.persistence.EntityManager import org.hibernate.Session +import org.hibernate.StatelessSession val EntityManager.session: Session get() = this.unwrap(org.hibernate.Session::class.java)!! @@ -10,3 +11,15 @@ fun EntityManager.flushAndClear() { this.flush() this.clear() } + + +inline fun EntityManager.doInStatelessSession( + crossinline block: (StatelessSession) -> T +): T { + return unwrap(Session::class.java).doReturningWork { connection -> + val statelessSession = unwrap(Session::class.java).sessionFactory.openStatelessSession(connection) + statelessSession.use { ss -> + block(ss) + } + } +}