Git Product home page Git Product logo

kotlin-jdsl's Introduction

Visit the gitbook for more information.

Kotlin JDSL

Kotlin JDSL is a Kotlin library that makes query building and execution easy. You can create queries using your own classes and Kotlin's built-in functions without an annotation processor, and easily execute them in your library.

Requirements

  • Java 8 or later if you are a user.
  • Kotlin 1.7 or later if you are a user.

How to reach us

Hall of fame

See the complete list of our contributors.

Contributors

kotlin-jdsl's People

Contributors

chicori3 avatar cj848 avatar erie0210 avatar esperar avatar graceful-martin avatar hadoobidoop avatar huisam avatar ilgolf avatar jaeykweon avatar jbl428 avatar jyunkim avatar key-del-jeeinho avatar kihwankim avatar leejejune avatar meengi07 avatar pemassi avatar pickmoment avatar progress0407 avatar renovate[bot] avatar saeyoon94 avatar seongyunkim avatar shouwn avatar sinkyoungdeok avatar theandreiursu avatar waahhh avatar waveofmymind avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlin-jdsl's Issues

Support Update Criteria API

In JPA Specification, Bulk Update Operation using Expression is also possible. We need to support this type of operation as well.
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/criteria/CriteriaUpdate.html

-- korean

JPA Specification 에는 Expression 을 이용한 Bulk Update Operation 도 가능합니다. 우리는 이 방식의 operation도 지원해야 합니다.
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/criteria/CriteriaUpdate.html

Type mismatch error

Hi,

I am trying to use jdsl for the first time and I am getting a strange error I am not able to resolve:

image

Probably there is a problem how the property is defined in the entity?

image

Support Delete Criteria API

In JPA Specification, Bulk Delete Operation using Expression is also possible. We need to support this type of operation as well.
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/criteria/CriteriaDelete.html

-- korean

JPA Specification 에는 Expression 을 이용한 Bulk Delete Operation 도 가능합니다. 우리는 이 방식의 operation도 지원해야 합니다.
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/criteria/CriteriaDelete.html

The Way reference key in select statement

Issue

Hello,
There are entities, I made. and I'd like to create the query below but I had a problem fetching reference key member_id from the member_role table in the subquery. Is it possible to extract the reference key from the associated entity class without join?

Entity class

@Entity
@Table(name = "members")
class MemberEntity(
    @Id
    @Column(name = "member_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0L,
    var name: String,
    @OneToMany(mappedBy = "member", cascade = [CascadeType.ALL], orphanRemoval = true)
    var memberRoles: MutableList<MemberRoleEntity> = ArrayList()
) : BaseEntity() {
    fun addRole(roleEntity: RoleEntity) {
        memberRoles.add(MemberRoleEntity(member = this, role = roleEntity))
    }
}

@Entity
@Table(name = "member_role")
class MemberRoleEntity(
    @Id
    @Column(name = "member_role_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0L,
    @JoinColumn(name = "member_id")
    @ManyToOne(fetch = FetchType.LAZY)
    var member: MemberEntity,
    @JoinColumn(name = "role_id")
    @ManyToOne(fetch = FetchType.LAZY)
    var role: RoleEntity,
) : BaseEntity()

@Entity
@Table(name = "roles")
class RoleEntity(
    @Id
    @Column(name = "role_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0L,
    var name: String
) : BaseEntity()

Query

select * from members
where 
	members.member_id in (
		select member_role.member_id
                 from member_role
                 inner join roles on member_role.role_id= roles.role_id
                 where roles.name in ("admin", "user")
    );
  • I can create this query below using Kotiln-JDSL and fetch member_id in subquery but I need to join with the member table
springDataQueryFactory
            .listQuery {
                select(entity(MemberEntity::class))
                from(MemberEntity::class)
                where(
                    col(MemberEntity::id).`in`(
                        springDataQueryFactory.subquery {
                            val memberRoleEntity: EntitySpec<MemberRoleEntity> = entity(MemberRoleEntity::class)
                            val innerQueryMemberEntity: EntitySpec<MemberEntity> = entity(MemberEntity::class, "inner_member")

                            select(col(innerQueryMemberEntity, MemberEntity::id))
                            from(memberRoleEntity)
                            join(memberRoleEntity, entity(RoleEntity::class), on(MemberRoleEntity::role), JoinType.INNER)
                            join(memberRoleEntity, innerQueryMemberEntity, on(MemberRoleEntity::member), JoinType.INNER)
                            where(col(RoleEntity::name).`in`(roleNames))
                        }
                    )
                )
            }
select * from members
where 
	members.member_id in (
		select inner_member.member_id
                 from member_role
                 inner join roles on member_role.role_id= roles.role_id
                 inner join members as inner_member on member_role.member_id = inner_member.member_id
                 where roles.name in ("admin", "user")
    );
  • in queryDSL I can get member_id(ref key) column value from member_role table without join using the syntax below.
    select(QMemberRoleEntity.memberRoleEntity.member.id) == select member_role.member_id

  • is there some way to fetch ref key

Include join examples

first of all this project is brilliant!
examples are all single entity oriented and not specifically helping with joins,
join has many overloads, i'm interested in left-join for instance and now i'm not sure which signature to use

nested column 지원이 안 되는데여..? (사용법 질문)

스크린샷 2022-09-27 오전 10 58 40

#79

    val sql:String =     """
            select
                s
            from
                Song s
            left join fetch s.album
                
            where
                s.id not in (
                    select
                        ps.song.id
                    from
                      PlaylistSong ps                     
                    where
                        ps.playlist.id=$playlistId
                )                                    
                order by s.id desc 
        """.trimIndent()

요런 식의 JPQL을 JDSL 로 바꾸고 싶은데..

        val songs = queryFactory.listQuery<Song> {
            select(entity(Song::class))
            from(entity(Song::class))
            fetch(Song::album, JoinType.LEFT)
            where(column(Song::id).`in`(playlistSongIdss))
        }

  1. JDSL 서브쿼리 쓸 때, fetch 구문은 못 쓰는거죠?
        val playlistSongIdss = queryFactory.subquery<Long> {
            select(column(Song::id))
            from(PlaylistSong::class)
            // fetch     //fetch 구문은 안 되는 듯.
            
            where(column(PlaylistSong::id).notEqual(playlistId))
        }
  1. nestedCol spec 도 없더라구요. 아직 release 을 안 한 건가요?
val playlistSongIdss = queryFactory.subquery<Long> {
            //select(nestedCol(col(PlaylistSong::song), Song::id)) 
            from(PlaylistSong::class)
            // fetch fetch 구문은 안 되는 듯.
            where(column(PlaylistSong::id).notEqual(playlistId))
        }

지금 현재 build.gradle

    implementation("com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter:2.0.5.RELEASE")

지금 상태로 저의 구문을 적절하게 Kotlin jdsl로 옮긴다면 어떤형태로 옮겨야될까요. 설명이나 예시가 너무 부족해서 쓰기가 힘듭니다..

Add support for paramters in `function` function

In QueryDSL we can use parameters like {0}, {1} to parse parameters.

But JDSL only supports varargs style functions.

Example (QueryDSL)

Simple example using QueryDSL

Expressions.dateTemplate(Date::class.java, "CAST({0} AS date)", QEntity.entity.createdAt).eq(date)

JSDL

I expected this would work like QueryDSL but it didn't.

function("CAST({0} AS date)", Date::class.java, col(Entity::createdAt)).equal(date)

Connection leak when coroutine canceled

kotlin-jdsl converts Uni to Coroutine through 'Mutiny#awaitSuspended'.
Look more closely here, the awaitSuspend function implemented by suspendCancellableCoroutine and invoke UniSubscriber#cancel when coroutine canceled.

However, hiberante-reactive MutinySessionFactoryImpl does not provide close process for cancel.

private<S extends Mutiny.Closeable, T> Uni<T> withSession(
          Uni<S> sessionUni,
          Function<S, Uni<T>> work,
          Context.Key<S> contextKey) {
        return sessionUni.chain( session -> Uni.createFrom().voidItem()
              .invoke( () -> context.put( contextKey, session ) )
              .chain( () -> work.apply( session ) )
              .eventually( () -> context.remove( contextKey ) )
              .eventually(session::close)
        );
}

below code not be executed when Uni(withSession) is canceled and Session not closed forever.

.eventually( () -> context.remove( contextKey ) )
.eventually(session::close)

Im not sure this hibernate-reactive session behavior is intended :(
related issue in hibernate-reactive issue

To use current version(1.1.9.Final) hibernate-reactive session, Uni must be converted to coroutine using suspendCoroutine instead of suspendCancellableCoroutine.

suspend fun <T> Uni<T>.awaitSingle() = suspendCoroutine<T> { continuation ->
    subscribe().with(
        { item -> continuation.resume(item) },
        { failure -> continuation.resumeWithException(failure) }
    )
}

사용법 문의

안녕하세요.
이번 자그마한 프로젝트에 queryDSL 대신 jdsl 넣어서 개발중입니다.
좋은 라이브러리 만들어 주셔서 감사합니다.
사용중 궁금한 점이 있어 문의 드립니다.

사용환경

  • kotlin-jdsl : 2.0.4

  • hibernate: 5.4.32

  • boot: 2.5.7

  1. 단건 select 방법
  • select count(id) from member 이런식으로 단건으로 리턴되는 쿼리 입니다.
  • 현재는 selectMulti를 사용해서 List로 fetch하고 첫번째 값만 리턴하고 있습니다.
  1. @Embedded 타입에 대한 column 사용법
  • 현재 날짜관련된 필드를 아래와 같이 사용하고 있습니다.
@Embeddable
class UpdatedAt(
    @Column(name = "updated_at")
    val ts: Long,

    @Column(name = "updated_date")
    val date: String,

    @Column(name = "updated_time")
    val time: String
) {
    companion object {
        fun create(ts: Long): UpdatedAt {
            return UpdatedAt(ts, toDateStr(ts), toTimeStr(ts))
        }
    }
}
  • 실제 쿼리에서는 UpdatedAt의 ts 필드만을 이용해서 between을 걸고 싶습니다.
  • column(SomObject::updatedAt::ts) 이런식으로 사용해보려 했는데 안되어서 어떤식으로 접근해야 하는지 궁금합니다.

Support Subquery Exists

image

Currently kotlin-jdsl does not support the CriteriaBuilder.exists method. An implementation of this method is required.

A function like below code should be implemented in jdsl.

think about what kind of appearance is suitable for jdsl.

-- korean
현재 kotlin-jdsl 은 CriteriaBuilder.exists 메소드를 지원하지 않습니다. 이 메소드의 구현이 필요합니다.

아래 코드와 같은 기능이 jdsl에 구현 되어야 합니다.

어떤 모습이 jdsl 에 적합한지 같이 고민해보았으면 합니다.

@shouwn @huisam @pickmoment

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
 
CriteriaQuery<Post> query = builder.createQuery(Post.class);
Root<Post> p = query.from(Post.class);
 
ParameterExpression<Integer> minScore = builder.parameter(Integer.class);
Subquery<Integer> subQuery = query.subquery(Integer.class);
Root<PostComment> pc = subQuery.from(PostComment.class);
subQuery
    .select(builder.literal(1))
    .where(
        builder.equal(pc.get(PostComment_.POST), p),
        builder.gt(pc.get(PostComment_.SCORE), minScore)
    );
 
query.where(builder.exists(subQuery));
 
List<Post> posts = entityManager.createQuery(query)
    .setParameter(minScore, 10)
    .getResultList();

generated SQL

SELECT
    p.id AS id1_0_,
    p.title AS title2_0_
FROM post p
WHERE EXISTS (
    SELECT 1
    FROM post_comment pc
    WHERE
        pc.post_id=p.id AND
        pc.score > ?
)
ORDER BY p.id

연관관계가 있는 Entity Delete 방법 질문

Issue 라는 부모 Entity 가 있고
Comment 라는 자식 Entity 가 1:N 관계를 가지고 있습니다.
Comment 는 issue_id라는 컬럼으로 Issue 의 ID를 FK로 가지고있습니다.

Issue 를 Delete 할 때 연관된 Comment 가 Casacade 로 전부 삭제되었으면 합니다.

다음의 세 가지 방법으로 삭제를 시도했으나 쿼리 실행 자체가 되질 않습니다.

queryFactory.deleteQuery<Issue> {
    where(
        col(Issue::id).equal(id)
    )
    associate(Comment::class, Issue::class, on(Comment::issue))
}
queryFactory.deleteQuery<Issue> {
    where(
        col(Issue::id).equal(id)
    )
    associate(Issue::class, Comment::class, on(Comment::issue))
}
queryFactory.deleteQuery<Issue> {
    where(
        col(Issue::id).equal(id)
    )
    associate(Issue::class, Comment::class, on(Issue::comments))
}

세 가지 방법 모두 자동 생성된 쿼리는 다음과 같습니다.

delete
from issues
where id=<입력된 id>

deleteQuery 구문 자체를 잘못 작성한건가요?
올바른 사용법이 어떻게 되는지 가르쳐 주셨으면 합니다.

아래는 Entity 파일 내용 입니다.

@Entity
@Table(name = "issues")
data class Issue(
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    @Column(name = "user_id")
    var userId: Long,

    @Column(name = "user_name")
    var userName: String,

    @OneToMany(
        fetch = FetchType.LAZY,
        mappedBy = "issue",
        cascade = [CascadeType.ALL],
        // orphanRemoval = true
    )
    val comments: Set<Comment> = emptySet(),

    @Column(name = "summary")
    var summary: String,

    @Column(name = "description")
    var description: String,

    @Column(name = "type")
    @Enumerated(EnumType.STRING)
    var type: IssueType,

    @Column(name = "priority")
    @Enumerated(EnumType.STRING)
    var priority: IssuePriority,

    @Column(name = "status")
    @Enumerated(EnumType.STRING)
    var status: IssueStatus,
)
@Entity
@Table(name = "comments")
data class Comment(
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "issue_id") // FK 외래키
    val issue: Issue,

    @Column(name = "user_id")
    val userId: Long,

    @Column(name = "user_name")
    val userName: String,

    @Column(name = "body")
    var body: String,
)

spring boot 3버전으로 업데이트시 JoinType문제

package com.linecorp.kotlinjdsl.querydsl.from

public inline fun <reified T : kotlin.Any, reified R : kotlin.Any> com.linecorp.kotlinjdsl.querydsl.from.FetchDsl.fetch(property: kotlin.reflect.KProperty1<T, R?>, joinType: javax.persistence.criteria.JoinType /* = compiled code /): kotlin.Unit { / compiled code */ }

@kotlin.jvm.JvmName public inline fun <reified T : kotlin.Any, reified R : kotlin.collections.Collection, reified E : kotlin.Any> com.linecorp.kotlinjdsl.querydsl.from.FetchDsl.fetch(property: kotlin.reflect.KProperty1<T, R?>, joinType: javax.persistence.criteria.JoinType /* = compiled code /): kotlin.Unit { / compiled code */ }

javax.persistence.criteria.JoinType 타입이 부트 3.0 업데이트되면서 삭제 되었는데 이부분은 처리할수 있는 방법이 있나요?

스크린샷 2023-01-26 오전 10 49 00

  • 버전은 implementation("com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter:2.2.0.RELEASE") 업데이트 했습니다.

pageQuery + join 쿼리 사용법 문의

안녕하세요. Kotlin, Webflux, Mysql 환경에서 jdsl을 사용하고 있습니다.
singleQueryOrNull, singleQuery, listQuery에서는 fetch 혹은 join 쿼리 정상 동작하는 것을 확인했는데요.
pageQuery 에서는 fetch 혹은 join 쿼리가 없는 것 같더라구요.
(fetch는 import가 안되고, join을 사용하면 could not initialize proxy - no Session 오류가 발생합니다)
참고로 fetchType은 EAGER로 설정해두었습니다.
혹시 지원 예정인걸까요? 아니면 제가 잘못 사용한 걸까요?

제가 사용했던 쿼리는 다음과 같습니다.

성공 쿼리

override suspend fun findById(competitionId: Long): Competition? {
        return queryFactory.singleQueryOrNull {
            select(entity(Competition::class))
            from(entity(Competition::class))
            fetch(Competition::prizes)
            where(col(Competition::id).equal(competitionId))
        }
    }

실패 쿼리 (import 안됨)

override suspend fun findAll(pageable: Pageable): Slice<Competition> {
        return queryFactory.pageQuery(pageable) {
            select(entity(Competition::class))
            from(entity(Competition::class))
            fetch(Competition::prizes)
        }
    }

감사합니다.

Equivalent of nested JOIN FETCH and LEFT JOIN FETCH

I am trying now to rewrite hibernate HQL to JDSL but I am not sure I know to convert JOIN FETCH and LEFT JOIN FETCH when they refer one to another

select DISTINCT i from myentity i JOIN FETCH i.translations t LEFT JOIN FETCH t.tags 

How we could achieve this?

join 관련 사용법 문의

안녕하세요.

QueryDSL 대신 jdsl 로 간단하게 토이프로젝트 돌려보며 방향성을 잡아 나가고 있습니다.

동일 테이블에 대한 join 을 어떻게 해야 할지 이리저리 해보다 안되서 문의 드립니다.

User 테이블에는 상위 User의 정보를 저장하는 parent_id가 있습니다.
User Entity에서는 연관관계 없이 사용하고 있습니다.
User(
id bigint,
parent_id bigint,
name varchar(100)
)

표현하고 싶은 쿼리는 아래와 같습니다.
문서에 join > alias쪽을 보았으나, native sql 처럼 풀어나가는 방법이 없는것 같아 문의 드립니다.
select u.id as my_id,
p.id as parent_id
from User u
left join User p on u.parent_id = u.id

Improve create object performance for QueryDslImpl & ReactiveQueryDslImpl

(Reactive)QueryDslImpl is an object created for every query creation and is used for select, update, and delete.
If you look inside this class, you can see the code that initializes mutableList(Map)Of at the time of object creation for used or unused clauses.

private var joins: MutableList<JoinSpec<*>> = mutableListOf()
private var wheres: MutableList<PredicateSpec> = mutableListOf()
private var groupBys: MutableList<ExpressionSpec<*>> = mutableListOf()
private var havings: MutableList<PredicateSpec> = mutableListOf()
private var orderBys: MutableList<OrderSpec> = mutableListOf()
private var sqlHints: MutableList<String> = mutableListOf()
private var jpaHints: MutableMap<String, Any> = mutableMapOf()
private var params: MutableMap<ColumnSpec<*>, Any?> = mutableMapOf()

Even though one very simple params is used only in update, for example, and the rest are unused, params are forcibly created as an empty MutableMap whenever select and delete queries are used.

In the case of mutableListOf , ArrayList is used internally, and this code has a default capacity of 10 (mutableMapOf is 16). In other words, you can see that you are wasting space by pre-creating an array that you may not even be using.

To solve this problem, we must either declare and use Lazy directly or implement by lazy { mutableListOf() } to create objects only when necessary as lazy.

However, createCriteriaQuerySpec, createCriteriaUpdateQuerySpec, createCriteriaDeleteQuerySpec, createSubquerySpec
When creating a spec through these four methods, note that all necessary clauses are always obtained, so that they are created only when necessary.

-- korean
(Reactive)QueryDslImpl 는 매 쿼리 생성마다 생성되는 객체이며 select, update, delete 모두에 사용 됩니다.
이 클래스의 내부를 살펴보면 사용 되거나 혹은 사용되지 않을 clause 들을 위해 mutableList(Map)Of 를 객체 생성 시점에 초기화 해두는 코드를 확인할 수 있습니다.

private var joins: MutableList<JoinSpec<*>> = mutableListOf()
private var wheres: MutableList<PredicateSpec> = mutableListOf()
private var groupBys: MutableList<ExpressionSpec<*>> = mutableListOf()
private var havings: MutableList<PredicateSpec> = mutableListOf()
private var orderBys: MutableList<OrderSpec> = mutableListOf()
private var sqlHints: MutableList<String> = mutableListOf()
private var jpaHints: MutableMap<String, Any> = mutableMapOf()
private var params: MutableMap<ColumnSpec<*>, Any?> = mutableMapOf()

이중 아주 간단한 params 하나를 예를 들면 update 에서만 사용되고 나머지는 사용되지 않음에도 select, delete 쿼리를 사용할때마다 params는 빈 MutableMap 으로 강제적으로 생성됩니다.

mutableListOf 의 경우 내부적으로 ArrayList 를 사용하고 있고 이 코드는 기본 capacity 가 10(mutableMapOf 는 16)입니다. 즉, 사용하지도 않을수도 있는 배열을 미리 생성해서 공간을 낭비하고 있는 것을 알 수 있습니다.

이러한 문제를 해결하기 위해 우리는 Lazy 를 직접 선언해서 사용하거나 by lazy { mutableListOf() } 를 통해 lazy 로 필요할때만 객체를 생성하게 구현하여야 합니다.

단, createCriteriaQuerySpec, createCriteriaUpdateQuerySpec, createCriteriaDeleteQuerySpec, createSubquerySpec
이 네개의 메소드를 통해 spec 을 생성할때 필요한 모든 clause 들을 항상 get 한다는 것에 주의하여 필요할때만 생성되도록 해야 합니다.

stuck polling waiting queue when reuse session

kotlin-jdsl : 2.0.7.RELEASE
coroutine : 1.6.4
vertx: 4.3.7

Im not sure this is the right approach, but the following code was used to reuse sessions and (transactions).

suspend fun reuseSession(userId: String) {
        queryFactory.statelessWithFactory {
            queryFactory.singleQuery {
                select(entity(User::class))
                from(entity(User::class))
                where(col(User::userId).equal(userId))
            }

            // reuse exist session
            queryFactory.singleQuery {
                select(entity(User::class))
                from(entity(User::class))
                where(col(User::userId).equal(userId))
            }
        }
}
[-worker-nio-3-2] o.h.r.m.impl.MutinySessionFactoryImpl    : No existing open Mutiny.StatelessSession was found in the current Vert.x context: opening a new instance
[ntloop-thread-1] o.h.r.pool.impl.SqlClientConnection      : Connection created: io.vertx.mysqlclient.impl.MySQLConnectionImpl@6b012c26
[ntloop-thread-1] o.h.r.m.impl.MutinySessionFactoryImpl    : Reusing existing open Mutiny.StatelessSession which was found in the current Vert.x context
[ntloop-thread-1] o.h.r.m.impl.MutinySessionFactoryImpl    : Reusing existing open Mutiny.StatelessSession which was found in the current Vert.x context
[ntloop-thread-1] o.h.r.pool.impl.SqlClientConnection      : Connection closed: io.vertx.mysqlclient.impl.MySQLConnectionImpl@6b012c26

[single request log]

If this function is executed above the maximum available of vert.x mysql pool, vert.x pool stuck with maximum queue pending.
vertx_sql_queue_pending{} 1000.0

It was a load test on armeria http server, so I'm not sure this problem cause by kotlin-jdsl.
for clearer test, the timeout of http server was set unlimited.

But, I found it works with vertx context dispatcher.

sessionFactory.withStatelessSession {
            // same issue when use 'CoroutineScope(SupervisorJob() + Dispatchers.Unconfined)'
            CoroutineScope(Vertx.currentContext().dispatcher())
                .async {
                    queryFactory.singleQuery {
                        select(entity(User::class))
                        from(entity(User::class))
                        where(col(User::userId).equal(userId))
                    }

                    // reuse exist session
                    queryFactory.singleQuery {
                        select(entity(User::class))
                        from(entity(User::class))
                        where(col(User::userId).equal(userId))
                    }
                }.asUni()
}.awaitSuspending()

Fetching multiple Entities of the same type

I'm not sure if I'm using the API wrong but when trying to fetch different entities of the same type from a parent entity only the last 'fetch' call works.

So an entity like this:

Job {
 collectionLocation: Location
 deliveryLocation: Location
}

calling
fetch(Job::collectionLocation) and then
fetch(Job::deliveryLocation)
results in only the delivery Location being joined in the final query.

I can also see another issue where I can't replicate this behaviour from Criteria API:

val colLoc = root.fetch(Job_.collectionLocation, JoinType.LEFT)
colLoc.fetch(LocationEntity_.address, JoinType.LEFT)

i.e fetching nested entities.

where 메소드 리팩토링

안녕하세요. jdsl에 흥미를 느껴 사이드 프로젝트에 적용해보고 있습니다.
where 절 관련해서 제언 사항이 있어 이슈와 pr을 올려보고자 합니다.

제가 하려고 하는 것은 무한 스크롤인데요. 일반적인 페이징이 아닌, no offset을 위해 입력받은 id를 기준으로 일정 개수만큼 쿼링하고자합니다. (참고 하고 있는 내용: https://jojoldu.tistory.com/528)

하지만 첫번째 페이지는 특성 상 id를 알기 어려운 것으로 알고 있습니다.
따라서 아래와 같은 코드를 작성하고 싶은데, null을 허용하지 않아 불가능합니다.

image
[그림 1 : 목표 코드]

우선 아래 두 가지 해결 방법을 찾았습니다. 하지만 코드가 (생각보다) 복잡해졌다고 생각합니다.

image
[그림 2: 해결 방법 1 - let 구문 안에 where 절 삽입]
image
[그림 3 : 해결 방법 2 - PredicateSpec.empty 사용]

lastTermId가 null일 경우, 그림 2와 그림 3의 코드 모두 where절을 만들지 않고 아래와 같은 쿼리를 만들었습니다

select
        termentity0_.id as col_0_0_ 
    from
        tb_term termentity0_ 
    order by
        termentity0_.id desc limit ?

빈 and()을 활용하는 방법도 있으나, 이 경우 where 1=1 이 포함된 쿼리가 생성되고, 이 쿼리는 매우 좋지 않은 것으로 알고 있습니다.

라이브러리를 다음과 같이 변경하면 좀 더 편하고 간결하게 사용할 수 있지 않을까 싶습니다
image
[그림 4 : where interface 리팩토링]
image
[그림 5 : QueryDslImpl 리팩토링]
또한 그림4와 그림 5의 코드를 통해 and()구문을 사용하지 않아도 되니, 좀 더 간결한 코드를 작성할 수 있지 않을까 합니다.

주니어 개발자라 아직 모르는 게 많아 틀릴 수 있으니 너그러이 봐주시면 감사하겠습니다.

Do you support nosql?

Hi guys.
We are using "spring-data-mongodb" library.

Can I use kotlin-jdsl with mongodb (nosql)?

THX.

How to use 'sum' expression with 'case-when'

I tried to convert below query to Kotlin-jdsl.

SELECT  id,
        SUM( CASE WHEN role IN ('A','B') THEN amount ELSE 0 END ) AS balance
FROM    TEST_TABLE
GROUP BY id
return query.listQuery {
    selectMulti(
        col(TestTable::id),
        sum(case(
          `when`(col(TestTable::role).`in`("A","B")).then(col(TestTable::occurAmount)),
          `else` = literal(0L)
        )),
    )
    from(entity(TestTable::class))
    groupBy(
        col(TestTable::id),
    )
}

But it could not possible because SumSpec might not support below syntax.

  sum(case(
    `when`(col(TestTable::role).`in`("A","B")).then(col(TestTable::occurAmount)),
    `else` = literal(0L)
  )),

Is there way to possible using sum expression with case-when ?

Support Criteria API's Alias

Currently, aliases in our library are only used for equality comparison of data classes. However, aliases in the actual JPQL also exist, and we must support them correctly.

-- korean
현재 우리 library의 alias 는 data class 의 동등성 비교를 위해서만 사용됩니다. 그러나 실제 JPQL에서의 alias 도 존재하며 이를 우리는 정확히 지원해야 합니다.

연관관계가 없는 Entity 간에 left join을 할 수 있는 방법이 있나요?

안녕하세요, 제공해주신 라이브러리를 유용하게 사용하고 있는 개발자입니다 :)

현재 QueryDSL을 대신하여 JDSL로 쿼리를 구성하고 있는데,
'연관관계가 없는 엔티티 간에 on 절을 이용하여 left join'을 해야하는 경우가 있습니다. 이렇게 조인해서 얻은 필드값은 DTO로 맵핑해서 반환하려고 합니다.

하지만 JDSL에서 제공하는 on절은 Cross Join만 가능하게 정의되어있는 것 같습니다.

https://github.com/line/kotlin-jdsl#cross-join

override fun <T> join(entity: EntitySpec<T>, predicate: PredicateSpec) {
    lazyJoins().add(CrossJoinSpec(entity))
    lazyWheres().add(predicate)
}

혹시 연관관계가 없는 두 엔티티를 left join 하는 방법이 있을까요?

Seperate JoinDsl.associate to AssociateDsl.associate

Associate is different from join. However, they do have one thing in common in mapping relationships, and this is necessary to accurately support future #28 and #29 issues.

-- korean
Associate 는 join 과 성격이 다릅니다. 그러나 관계를 매핑하는데 있어서 공통점을 가지고 있고 이부분은 향후 #28 #29 이슈를 정확히 지원하기 위해 필요합니다.

Entity 객체 전체를 넘겨서 업데이트 하는 쉬운 방법이 있나요?

안녕하세요!
Entity 객체 전체를 넘겨서 업데이트 하는 쉬운 방법이 있나요?

JpaRepository 에서는 아래처럼 쉽게 업데이트가 가능했습니다.

val updated = repository.save(bus) // S save(S entity) 

kotlin-jdsl 로는, 아래처럼 써야하는데요,

fun save(bus: Bus): Bus {
       queryFactory.updateQuery<Bus> {
            where(col(Bus::id).equal(bus.id))
            setParams(col(Bus::columnA) to bus.columnA)
            setParams(col(Bus::columnB) to bus.columnB)
        }.executeUpdate()

        return queryFactory.singleQuery<Bus> {
            select(entity(Bus::class))
            from(entity(Bus::class))
            where(col(Bus::id).equal(bus.id))
        }
}

Bus Entity Class 에 컬럼이 추가될때마다 save 함수를 고쳐야 했습니다.

저는

  1. Entity Object 를 넘겨서 모든 컬럼을 업데이트를 하고 싶습니다.
  2. 업데이트 된 객체를 반환 하고 싶습니다.

위 예제 코드보다 간단한 방법이 있나요?

(참고로 entityManager.merge 를 사용하지 않는 이유는 update 할때 where 조건을 커스터마이징하기 위함입니다)

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/build.yaml
  • actions/checkout v4@3df4ab11eba7bda6032a0b82a6bb43b11571feac
  • actions/setup-java v3
  • gradle/wrapper-validation-action v1
  • codecov/codecov-action v3
  • EnricoMi/publish-unit-test-result-action v2
.github/workflows/commit_lint.yaml
  • actions/checkout v4@3df4ab11eba7bda6032a0b82a6bb43b11571feac
  • actions/setup-node v3
gradle
buildSrc/src/main/kotlin/JacocoExtensionPlugin.kt
buildSrc/src/main/kotlin/LocalPropertiesPlugin.kt
buildSrc/src/main/kotlin/Modules.kt
buildSrc/src/main/kotlin/Plugins.kt
buildSrc/src/main/kotlin/PublishPlugin.kt
buildSrc/src/main/kotlin/Utils.kt
gradle.properties
libs.versions.toml
  • javax.persistence:javax.persistence-api 2.2
  • jakarta.persistence:jakarta.persistence-api 3.1.0
  • org.slf4j:slf4j-api 2.0.9
  • ch.qos.logback:logback-classic 1.2.11
  • org.hibernate:hibernate-core 6.2.7.Final
  • org.hibernate:hibernate-core 5.6.15.Final
  • org.hibernate.reactive:hibernate-reactive-core 1.1.9.Final
  • org.hibernate.reactive:hibernate-reactive-core-jakarta 1.1.9.Final
  • org.eclipse.persistence:org.eclipse.persistence.jpa 2.7.13
  • org.eclipse.persistence:org.eclipse.persistence.jpa 4.0.2
  • io.agroal:agroal-pool 2.2
  • io.vertx:vertx-jdbc-client 4.4.5
  • org.jetbrains.kotlinx:kotlinx-coroutines-jdk8 1.7.3
  • org.jetbrains.kotlinx:kotlinx-coroutines-reactor 1.7.3
  • org.springframework.boot:spring-boot-starter 2.7.15
  • org.springframework.boot:spring-boot-autoconfigure 2.7.15
  • org.springframework.boot:spring-boot-configuration-processor 2.7.15
  • org.springframework.boot:spring-boot-dependencies 2.7.15
  • org.springframework.boot:spring-boot-starter-web 2.7.15
  • org.springframework.boot:spring-boot-starter-webflux 2.7.15
  • org.springframework.boot:spring-boot-starter-data-jpa 2.7.15
  • org.springframework.boot:spring-boot-starter-test 2.7.15
  • org.springframework.boot:spring-boot-starter 3.1.3
  • org.springframework.boot:spring-boot-autoconfigure 3.1.3
  • org.springframework.boot:spring-boot-configuration-processor 3.1.3
  • org.springframework.boot:spring-boot-dependencies 3.1.3
  • org.springframework.boot:spring-boot-starter-web 3.1.3
  • org.springframework.boot:spring-boot-starter-webflux 3.1.3
  • org.springframework.boot:spring-boot-starter-data-jpa 3.1.3
  • org.springframework.boot:spring-boot-starter-test 3.1.3
  • org.springframework:spring-core 5.3.29
  • org.springframework:spring-beans 5.3.29
  • org.springframework.data:spring-data-jpa 2.7.15
  • org.springframework.batch:spring-batch-infrastructure 4.3.9
  • org.springframework:spring-core 6.0.11
  • org.springframework:spring-beans 6.0.11
  • org.springframework.data:spring-data-jpa 3.1.3
  • org.springframework.batch:spring-batch-infrastructure 5.0.3
  • org.junit.jupiter:junit-jupiter 5.10.0
  • org.assertj:assertj-core 3.24.2
  • io.mockk:mockk 1.13.7
  • com.h2database:h2 2.2.222
  • io.smallrye.reactive:mutiny 2.4.0
  • io.smallrye.reactive:mutiny-kotlin 2.4.0
  • org.springframework.boot 2.7.15
  • org.springframework.boot 3.1.3
  • org.jetbrains.kotlin.plugin.allopen 1.9.10
  • org.jetbrains.kotlin.plugin.noarg 1.9.10
  • org.jetbrains.kotlin.jvm 1.9.10
settings.gradle.kts
build.gradle.kts
buildSrc/build.gradle.kts
core/build.gradle.kts
core-jakarta/build.gradle.kts
eclipselink/build.gradle.kts
eclipselink-jakarta/build.gradle.kts
hibernate/build.gradle.kts
hibernate-jakarta/build.gradle.kts
hibernate-reactive/build.gradle.kts
hibernate-reactive-jakarta/build.gradle.kts
query/build.gradle.kts
query-jakarta/build.gradle.kts
reactive-core/build.gradle.kts
reactive-core-jakarta/build.gradle.kts
spring/batch-infrastructure/build.gradle.kts
spring/batch-infrastructure-jakarta/build.gradle.kts
spring/data-autoconfigure/build.gradle.kts
spring/data-autoconfigure-jakarta/build.gradle.kts
spring/data-core/build.gradle.kts
spring/data-core-jakarta/build.gradle.kts
spring/data-hibernate-reactive/build.gradle.kts
spring/data-hibernate-reactive-jakarta/build.gradle.kts
spring/data-reactive-core/build.gradle.kts
spring/data-reactive-core-jakarta/build.gradle.kts
spring/data-starter/build.gradle.kts
spring/data-starter-jakarta/build.gradle.kts
test-fixture/core/build.gradle.kts
test-fixture/entity/build.gradle.kts
test-fixture/entity-jakarta/build.gradle.kts
test-fixture/hibernate-reactive/build.gradle.kts
test-fixture/hibernate-reactive-jakarta/build.gradle.kts
test-fixture/integration/build.gradle.kts
test-fixture/integration-jakarta/build.gradle.kts
test-fixture/integration-reactive/build.gradle.kts
test-fixture/integration-reactive-jakarta/build.gradle.kts
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 8.2.1
npm
package.json
  • @commitlint/cli 17.7.1
  • @commitlint/config-conventional 17.7.0

  • Check this box to trigger a request for Renovate to run again on this repository

Support hibernate-reactive

hibernate reactive is a library that allows reactive DB access while using the jpa criteria API as it is, and it looks like a good project to be supported by kotlin-jdsl.

We would like to support this library and provide reactive jdsl.

-- korean
hibernate reactive 는 jpa criteria API 를 그대로 사용하면서 reactive 한 DB 접근을 할 수 있는 라이브러리로 kotlin-jdsl 에서 지원하기 좋은 프로젝트로 보입니다. 우리는 이 라이브러리를 지원해서 reactive 한 jdsl 을 제공하면 좋겠습니다.

Support JPA 3.0 Specification for Reactive

Currently, hibernate-reactive does not support the JPA 3.0 specification.
When the hibernate-reactive library comes to support the JPA 3.0 specification, we should support it too. (issue: hibernate/hibernate-reactive#1052)

The current synchronous version of the JPA 3.0 specification is already supported. (#27)
However, we currently do not support the reactive JPA 3.0 specification and we must support it.

Transaction doesn't work if there's a call to an additional suspend function

				factory.transactionWithFactory { session, _ ->
					val entity = TestEntity(title = Title("should succeed"))
					session.persist(entity)
						.chain(Supplier { session.flush() })
						.replaceWith(entity)
						.awaitSuspending()
					delay(2000)
				}

^ this code breaks, this means that I can't run a transaction and call external suspend function without breaking the code
Is there something I'm missing?
how can I do multiple things in a transaction like - get -> async big calculation -> save

column String to Int 질문

안녕하세요.
제공해주신 kotlin-jdsl 사용 중에 궁금한 점이 있어 질문 드립니다.

  1. pageQuery에서는 groupBy를 사용할 수 없게 되어있어서 현재는 listQuery로 받아 PageImpl로 변환하여 사용하고 있습니다.
    더 좋은 방법이 있을지 의견 주시면 감사하겠습니다.

  2. equal로 비교하는 column간 타입이 다른 경우 어떻게 사용하면 좋을지 의견 부탁 드립니다.
    querydsl의 경우 castToNum을 사용하면 string타입을 NumberExpression으로 변환해주는 것으로 알고 있는데, jdsl에서는 방법을 찾지 못했습니다.

image

  • 좌측이 int, 우측이 string 타입입니다.

image

버전 : hibernate-reactive-kotlin-jdsl-2.0.4.RELEASE

감사합니다.

Add BlockHound for Reactive Integration Test

-- english
BlockHound is a library that can detect blocking that should not happen inside Reactor, Coroutine, and RxJava methods.
We need to apply this library to all tests in the reactive module to prevent possible blocking situations.

-- korean
BlockHound 는 Reactor, Coroutine, RxJava 메소드 내부에서 일어나면 안되는 Blocking 을 감지할 수 있는 라이브러리 입니다.
우리는 이 라이브러리를 Reactive 모듈의 모든 테스트에 적용해 혹시나 있을 수 있는 Blocking 상황을 방지해야 합니다.

Support JPA 3.0 Specification

JPA 3.0 is a specification created to avoid patent disputes with Java, and compared to 2.2, there is no difference except for package and name.

Comparing the case of Hibernate, it is supported as a separate library like hibernate-core-jakarta.

It seems that kotlin-jdsl and kotlin-jdsl-core-jakarta should come out in pairs.

Currently, JPA 3.0 specification supports only two vendors, Eclipselink and Hibernate.

-- korean
JPA 3.0 은 Java 와의 특허 분쟁을 피하기 위해 만들어진 스펙으로 실제 2.2와 비교해보면 package 나 명칭 제외하고는 다르지 않습니다.

하이버네이트의 사례를 비교해 보면 hibernate-core-jakarta 와 같이 별도의 라이브러리로 지원하고 있습니다.

kotlin-jdsl 도 kotlin-jdsl-core-jakarta 와 같은 형태의 쌍들이 나와야 할 것으로 보입니다.

현재 JPA 3.0 스펙은 Eclipselink, Hibernate 두개의 vendor 만 지원하고 있습니다.

Java Class Entity 호출 이슈

안녕하세요.
해당 라이브러리를 잘 쓰고 있습니다.

현재 제 프로젝트에서는 Java Entity를 사용하고 있고, Kotlin jdsl 에서 Java Entity를 호출해 사용하려고합니다.

기본적으로 kotlin은 private을 붙이지 않으면 외부 참조가 가능한걸로 돼있는데,
Java Class 필드는 보통 private을 붙여서 사용하고 있습니다.

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RevealPosition extends BaseTimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "position_id")
    private Long id;

image

해당 사진과 같이 호출을 하고 싶으나 할수 없는 상태입니다.

자바 Entity를 해당 KProperty로 바꾸려고 시도는 해봤는데, 잘 모르겠습니다.
property: KProperty1<T, R>

자바 Entity도 호출할수 있는 아이디어 주시면 감사하겠습니다!

혹시 not in 절 지원안하나요? join 질문

안녕하세요! queryDsl 만 써보다가 최근 코틀린-jdsl을 접하고, 최대한 바꿔볼려고 노력하고 있습니다. 변경작업 중에 몇가지 질문이 있어서 여쭤봅니다.

     List<Song> fetch = queryFactory
                .selectFrom(song)
                .where(
                        song.id.notIn(
                        JPAExpressions
                                .select(playlistSong.song.id)
                                .from(playlistSong)
                                .where(playlistSong.playlist.id.eq(playlistId)))
                )
                .limit(pageable.getPageSize())
                .offset(pageable.getOffset())
                .fetch();

queyrdsl로 만든 요런 쿼리를 kotiln jdsl로 바꿔볼려고 하는데


    val artistSongs = queryFactory.subquery<PlaylistSong>  {
        select(entity(PlaylistSong::class))
        from(entity(PlaylistSong::class))
        where(
            column(PlaylistSong::song).notEqual(Playlist())
        )
    }

 queryFactory.listQuery<Song> {
            select(entity(Song::class))
            from(entity(Song::class))
            where(
                column(Song::id).`in`(???)
            )

        }

단방향 연관관계로만 구성했고요.
어떻게 비슷하게 만들어보려 했는데, 여기서 의문점이 연관관계 엔티티를 조회할때, 항상 객체참조를 넘겨줘야 외래키인 Id 값을 비교하는 것 같은데
querydsl로 id값만 넘겨줘서 비교하는 것도 가능한가요?
그러니까

  column(PlaylistSong::song::id) //요런 식으로 연관관계 엔티티의 필드를 조건으로 넘길 수 있을까요?

좋은 오픈소스 제공해주셔서 갑사합니다..

Support function so that User can define each DB function

Implement FunctionSpec

  • User can use the each DB function using function expression.
  • User can define a new DSL method using function expression.

examples

data class FunctionSpec<T>(
    val name: String,
    val returnType: Class<T>,
    val expressions: List<ExpressionSpec<*>>,
) : ExpressionSpec<T>


fun mod(left: Int, right: Int) = FunctionSpec("mod", Int::class.java, listOf(literal(left), literal(right)))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.