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

kotlin jdsl 3 #169

Merged
merged 9 commits into from
Oct 28, 2023
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