Skip to content

Commit

Permalink
Merge pull request #169 from santa-close/feat/kotlin-jdsl-3
Browse files Browse the repository at this point in the history
kotlin jdsl 3
  • Loading branch information
jbl428 authored Oct 28, 2023
2 parents 01f519a + 308787f commit 292549c
Show file tree
Hide file tree
Showing 20 changed files with 262 additions and 190 deletions.
11 changes: 9 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ jjwt-jackson = { module = "io.jsonwebtoken:jjwt-jackson", version.ref = "jjwt" }

hibernate-spatial = { module = "org.hibernate:hibernate-spatial", version = "6.2.6.Final" }

kotlin-jdsl = { module = "com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter-jakarta", version = "2.2.1.RELEASE" }

database-h2 = { module = "com.h2database:h2" }
connector-mysql = { module = "com.mysql:mysql-connector-j" }

kotlin-jdsl-jpql-dsl = { module = "com.linecorp.kotlin-jdsl:jpql-dsl", version = "3.0.0" }
kotlin-jdsl-jpql-render = { module = "com.linecorp.kotlin-jdsl:jpql-render", version = "3.0.0" }
kotlin-jdsl-spring-data-jpa-support = { module = "com.linecorp.kotlin-jdsl:spring-data-jpa-support", version = "3.0.0" }

## test
spring-starter-test = { module = "org.springframework.boot:spring-boot-starter-test" }
spring-graphql-test = { module = "org.springframework.graphql:spring-graphql-test" }
Expand Down Expand Up @@ -75,6 +77,11 @@ kotlin-libs = [
"reactor-kotlin-extensions",
"jackson-module-kotlin",
]
kotlin-jdsl = [
"kotlin-jdsl-jpql-dsl",
"kotlin-jdsl-jpql-render",
"kotlin-jdsl-spring-data-jpa-support",
]

## test
kotest = ["kotest-runner-junit5", "kotest-assertions-arrow", "kotest-extensions-spring"]
Expand Down
2 changes: 1 addition & 1 deletion server-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies {
implementation(libs.spring.security)
implementation(libs.spring.data.jpa)
implementation(libs.hibernate.spatial)
implementation(libs.kotlin.jdsl)
implementation(libs.bundles.kotlin.jdsl)
implementation(libs.jjwt.api)

runtimeOnly(libs.jjwt.impl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,33 @@ package com.santaclose.app.appUser.repository

import arrow.core.Either
import arrow.core.Either.Companion.catch
import com.linecorp.kotlinjdsl.querydsl.expression.col
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.listQuery
import com.linecorp.kotlinjdsl.dsl.jpql.jpql
import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderContext
import com.linecorp.kotlinjdsl.support.spring.data.jpa.extension.createQuery
import com.santaclose.lib.entity.appUser.AppUser
import jakarta.persistence.EntityManager
import org.springframework.stereotype.Repository

@Repository
class AppUserAppQueryRepositoryImpl(
private val springDataQueryFactory: SpringDataQueryFactory,
private val entityManager: EntityManager,
private val jpqlRenderContext: JpqlRenderContext,
) : AppUserAppQueryRepository {
override fun findBySocialId(socialId: String): Either<Throwable, AppUser?> = catch {
springDataQueryFactory
.listQuery<AppUser> {
select(entity(AppUser::class))
from(AppUser::class)
where(col(AppUser::socialId).equal(socialId))
limit(1)
}
val query = jpql {
select(
entity(AppUser::class),
).from(
entity(AppUser::class),
).where(
path(AppUser::socialId).eq(socialId),
)
}

entityManager
.createQuery(query, jpqlRenderContext)
.apply { maxResults = 1 }
.resultList
.firstOrNull()
}
}
Original file line number Diff line number Diff line change
@@ -1,54 +1,57 @@
package com.santaclose.app.mountain.repository

import arrow.core.Either
import arrow.core.recover
import com.linecorp.kotlinjdsl.querydsl.expression.col
import com.linecorp.kotlinjdsl.querydsl.from.fetch
import com.linecorp.kotlinjdsl.querydsl.from.join
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.listQuery
import com.linecorp.kotlinjdsl.spring.data.singleQuery
import com.linecorp.kotlinjdsl.dsl.jpql.jpql
import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderContext
import com.linecorp.kotlinjdsl.support.spring.data.jpa.extension.createQuery
import com.santaclose.app.mountain.repository.dto.MountainLocationDto
import com.santaclose.lib.entity.location.Location
import com.santaclose.lib.entity.mountain.Mountain
import com.santaclose.lib.entity.mountainRestaurant.MountainRestaurant
import com.santaclose.lib.entity.restaurant.Restaurant
import com.santaclose.lib.web.exception.DomainError.DBFailure
import com.santaclose.lib.web.exception.catchDB
import jakarta.persistence.NoResultException
import jakarta.persistence.criteria.JoinType
import jakarta.persistence.EntityManager
import org.springframework.stereotype.Repository

@Repository
class MountainAppQueryRepositoryImpl(
private val springDataQueryFactory: SpringDataQueryFactory,
private val entityManager: EntityManager,
private val jpqlRenderContext: JpqlRenderContext,
) : MountainAppQueryRepository {

override fun findOneWithLocation(id: Long): Either<DBFailure, Mountain?> =
Either.catch {
springDataQueryFactory.singleQuery {
select(entity(Mountain::class))
from(Mountain::class)
fetch(Mountain::location, JoinType.INNER)
where(col(Mountain::id).equal(id))
}
}.recover {
if (it is NoResultException) {
null
} else {
raise(DBFailure(it))
Either.catchDB {
val query = jpql {
select(
entity(Mountain::class),
).from(
entity(Mountain::class),
innerFetchJoin(Mountain::location),
).where(
path(Mountain::id).eq(id),
)
}

entityManager.createQuery(query, jpqlRenderContext).resultList.firstOrNull()
}

override fun findLocationByRestaurant(restaurantId: Long): Either<DBFailure, List<MountainLocationDto>> =
Either.catchDB {
springDataQueryFactory.listQuery {
selectMulti(col(Mountain::id), col(Location::point))
from(Mountain::class)
join(Mountain::mountainRestaurant, JoinType.INNER)
join(MountainRestaurant::restaurant, JoinType.INNER)
join(Mountain::location, JoinType.INNER)
where(col(Restaurant::id).equal(restaurantId))
val query = jpql {
selectNew<MountainLocationDto>(
path(Mountain::id),
path(Location::point),
).from(
entity(Mountain::class),
innerJoin(Mountain::mountainRestaurant),
innerJoin(MountainRestaurant::restaurant),
innerJoin(Mountain::location),
).where(
path(Restaurant::id).eq(restaurantId),
)
}

entityManager.createQuery(query, jpqlRenderContext).resultList
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,67 @@
package com.santaclose.app.mountainRestaurant.repository

import arrow.core.Either
import com.linecorp.kotlinjdsl.querydsl.expression.col
import com.linecorp.kotlinjdsl.querydsl.from.join
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.listQuery
import com.linecorp.kotlinjdsl.dsl.jpql.jpql
import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderContext
import com.linecorp.kotlinjdsl.support.spring.data.jpa.extension.createQuery
import com.santaclose.app.mountainRestaurant.repository.dto.LatestMountainDto
import com.santaclose.app.mountainRestaurant.repository.dto.LatestRestaurantDto
import com.santaclose.lib.entity.mountain.Mountain
import com.santaclose.lib.entity.mountainRestaurant.MountainRestaurant
import com.santaclose.lib.entity.restaurant.Restaurant
import com.santaclose.lib.web.exception.DomainError.DBFailure
import com.santaclose.lib.web.exception.catchDB
import jakarta.persistence.criteria.JoinType
import jakarta.persistence.EntityManager
import org.springframework.stereotype.Repository

@Repository
class MountainRestaurantAppQueryRepositoryImpl(
private val springDataQueryFactory: SpringDataQueryFactory,
private val entityManager: EntityManager,
private val jpqlRenderContext: JpqlRenderContext,
) : MountainRestaurantAppQueryRepository {
override fun findMountainByRestaurant(id: Long, limit: Int): Either<DBFailure, List<LatestMountainDto>> =
Either.catchDB {
springDataQueryFactory.listQuery {
selectMulti(col(Mountain::id), col(Mountain::name))
from(MountainRestaurant::class)
join(MountainRestaurant::mountain, JoinType.INNER)
join(MountainRestaurant::restaurant, JoinType.INNER)
where(col(Restaurant::id).equal(id))
orderBy(col(Mountain::id).desc())
limit(limit)
val query = jpql {
selectNew<LatestMountainDto>(
path(Mountain::id),
path(Mountain::name),
).from(
entity(Mountain::class),
innerJoin(Mountain::mountainRestaurant),
innerJoin(MountainRestaurant::restaurant),
).where(
path(Restaurant::id).eq(id),
).orderBy(
path(Mountain::id).desc(),
)
}

entityManager
.createQuery(query, jpqlRenderContext)
.apply { maxResults = limit }
.resultList
}

override fun findRestaurantByMountain(id: Long, limit: Int): Either<DBFailure, List<LatestRestaurantDto>> =
Either.catchDB {
springDataQueryFactory.listQuery {
selectMulti(col(Restaurant::id), col(Restaurant::name))
from(MountainRestaurant::class)
join(MountainRestaurant::mountain, JoinType.INNER)
join(MountainRestaurant::restaurant, JoinType.INNER)
where(col(Mountain::id).equal(id))
orderBy(col(Restaurant::id).desc())
limit(limit)
val query = jpql {
selectNew<LatestRestaurantDto>(
path(Restaurant::id),
path(Restaurant::name),
).from(
entity(MountainRestaurant::class),
innerJoin(MountainRestaurant::mountain),
innerJoin(MountainRestaurant::restaurant),
).where(
path(Mountain::id).eq(id),
).orderBy(
path(Restaurant::id).desc(),
)
}

entityManager
.createQuery(query, jpqlRenderContext)
.apply { maxResults = limit }
.resultList
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,68 @@ package com.santaclose.app.mountainReview.repository

import arrow.core.Either
import arrow.core.recover
import com.linecorp.kotlinjdsl.query.spec.expression.EntitySpec
import com.linecorp.kotlinjdsl.querydsl.expression.avg
import com.linecorp.kotlinjdsl.querydsl.expression.col
import com.linecorp.kotlinjdsl.querydsl.from.fetch
import com.linecorp.kotlinjdsl.querydsl.from.join
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.listQuery
import com.linecorp.kotlinjdsl.spring.data.singleQuery
import com.linecorp.kotlinjdsl.dsl.jpql.jpql
import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderContext
import com.linecorp.kotlinjdsl.support.spring.data.jpa.extension.createQuery
import com.santaclose.app.mountainReview.repository.dto.MountainRatingAverageDto
import com.santaclose.lib.entity.mountain.Mountain
import com.santaclose.lib.entity.mountainReview.MountainRating
import com.santaclose.lib.entity.mountainReview.MountainReview
import com.santaclose.lib.web.exception.DomainError.DBFailure
import com.santaclose.lib.web.exception.catchDB
import jakarta.persistence.EntityManager
import jakarta.persistence.PersistenceException
import jakarta.persistence.criteria.JoinType
import org.springframework.stereotype.Repository

@Repository
class MountainReviewAppQueryRepositoryImpl(
private val springDataQueryFactory: SpringDataQueryFactory,
private val entityManager: EntityManager,
private val jpqlRenderContext: JpqlRenderContext,
) : MountainReviewAppQueryRepository {

override fun findAllByMountainId(mountainId: Long, limit: Int): Either<DBFailure, List<MountainReview>> =
Either.catchDB {
springDataQueryFactory.listQuery {
val mountainReview: EntitySpec<MountainReview> = entity(MountainReview::class)
select(mountainReview)
from(mountainReview)
fetch(MountainReview::mountain, JoinType.INNER)
where(col(Mountain::id).equal(mountainId))
orderBy(col(Mountain::id).desc())
limit(limit)
val query = jpql {
select(
entity(MountainReview::class),
).from(
entity(MountainReview::class),
innerJoin(MountainReview::mountain),
).where(
path(Mountain::id).eq(mountainId),
).orderBy(
path(Mountain::id).desc(),
)
}

entityManager
.createQuery(query, jpqlRenderContext)
.apply { maxResults = limit }
.resultList
}

override fun findMountainRatingAverages(mountainId: Long): Either<DBFailure, MountainRatingAverageDto> =
Either.catch<MountainRatingAverageDto> {
springDataQueryFactory.singleQuery {
val mountainReview: EntitySpec<MountainReview> = entity(MountainReview::class)
selectMulti(
avg(MountainRating::scenery),
avg(MountainRating::tree),
avg(MountainRating::trail),
avg(MountainRating::parking),
avg(MountainRating::toilet),
avg(MountainRating::traffic),
count(col(MountainReview::id)),
val query = jpql {
selectNew<MountainRatingAverageDto>(
avg(path(MountainReview::rating)(MountainRating::scenery)),
avg(path(MountainReview::rating)(MountainRating::tree)),
avg(path(MountainReview::rating)(MountainRating::trail)),
avg(path(MountainReview::rating)(MountainRating::parking)),
avg(path(MountainReview::rating)(MountainRating::toilet)),
avg(path(MountainReview::rating)(MountainRating::traffic)),
count(MountainReview::id),
).from(
entity(MountainReview::class),
innerJoin(MountainReview::mountain),
).where(
path(Mountain::id).eq(mountainId),
)
associate(MountainReview::class, MountainRating::class, on(MountainReview::rating))
from(mountainReview)
join(MountainReview::mountain, JoinType.INNER)
where(col(Mountain::id).equal(mountainId))
}

entityManager
.createQuery(query, jpqlRenderContext)
.singleResult
}.recover {
if (it is PersistenceException) {
MountainRatingAverageDto.empty
Expand Down
Loading

0 comments on commit 292549c

Please sign in to comment.