line / kotlin-jdsl

Kotlin library that makes it easy to build and execute queries without generated metamodel
https://kotlin-jdsl.gitbook.io/docs/
Apache License 2.0
711 stars 88 forks source link

Do you support Parameterized Query? #46

Closed debop closed 2 years ago

debop commented 2 years ago

I can't find feature to build parameterized query

ref: https://www.baeldung.com/jpa-query-parameters

I want to reuse TypedQuery with named parameters

Can you support this?

cj848 commented 2 years ago

In what cases are you trying to use it? If you want to use TypedQuery itself If you use this method (https://github.com/line/kotlin-jdsl/blob/main/core/src/main/kotlin/com/linecorp/kotlinjdsl/QueryFactoryExtensions.kt#L25), you can return a TypedQuery and process setParameter or other parameters.

However, the purpose of our library is not to consider how to support parameters with a plain query string.. This is because the purpose is to create a code-based query rather than a plain query through the Criteria API. For that reason, Plain JPQL and Native Query is not supported. If you need those two, you can directly create a query through EntityManager and use it.

-- korean 어떤 경우에 활용하시려고 하시는걸까요? TypedQuery 자체를 활용하고 싶으시다면 이 메소드(https://github.com/line/kotlin-jdsl/blob/main/core/src/main/kotlin/com/linecorp/kotlinjdsl/QueryFactoryExtensions.kt#L25) 를 사용하시면 TypedQuery 를 리턴 받아서 setParameter나 기타 다른 파라메터 처리를 하실 수 있습니다.

그러나 저희 라이브러리의 목적 자체가 plain query 스트링을 가지고 파라메터를 지원하려는 방식을 고려하고 있지는 않습니다. Criteria API 를 통한 Plain 쿼리가 아닌 코드 기반의 쿼리를 만들어내려고 하는게 목적이기 때문입니다. 그런 이유로 Plain JPQL, Native Query 를 지원하지 않고 있습니다. 그 두가지가 필요하다면 쿼리를 직접 EntityManager 를 통해 생성하고 사용하시면 됩니다.

debop commented 2 years ago

QueryFactory.selectQuery() 등으로 TypedQuery 를 빌드할 때 Parameterized Query 를 만들면 재사용이 가능하리라 생각했습니다. 또한 Plain SQL이 parameterized 가 안되면 DB 성능이 떨어진다고 알고 있어서요

어쩔 수 없이 TypedQuery 를 직접 조작해야겠네요

shouwn commented 2 years ago

-- korean

두 가지 관점이 있는 것 같습니다.

재활용성

람다 혹은 메소드를 통해서 코드를 재활용할 수 있지만 이 부분을 말씀해주시는 것은 아닌 것 같습니다. 람다 혹은 메소드를 통해서 재활용하게 되면 쿼리 객체가 여러개 생성 되어 불필요한 메모리를 점유한다고 생각하셔서 말씀해주신 것으로 이해됩니다.

이 부분은 저희 쿼리 객체에 값이 assigne 되어 있기 때문에 불가능한 부분입니다. 차후 가능하도록 만들 수 있는지 검토해보겠습니다.

SQL 쿼리의 값이 ? 로 변수화 되어서 전달 되는지 여부

SQL 쿼리가 Parameterized 되는 것은 TypedQuery에서 작업이 아닌 것으로 알고 있습니다. 이 부분은 JPA 구현체에 따라 다르겠지만 기본적으로 SQL 쿼리를 Parameterized 해주는 것으로 알고 있습니다.

Hibernate의 경우가 그렇습니다. 하지만 Hibernate의 경우도 Long과 같은 값은 Parameterized 해주지 않는데요.

그럴 경우 criteria.literal_handling_mode: BIND 설정을 참고하시면 좋을 것 같습니다.

debop commented 2 years ago

@shouwn 답변 감사합니다. 저도 구글링에서 hibernate.critiera.literal_handling_mode=bind 를 사용해서 query 를

    select
        sqrt(order0_.purchaser_id) as col_0_0_ 
    from
        test_order order0_ 
    where
        order0_.purchaser_id=? limit ?

이렇게 만드는 게 되네요 ^^

제가 Hibernate 4.x 대에서 떠난 후 이제 다시 공부하게 되어서, 용어나 의미에 혼동을 드린 것 같네요^^

우선은 위 기능으로 DB 의 Prepared Statement 는 지원되는 걸 확인했습니다.

예전 Hibernate의 DetachedCriteria 처럼 TypedQuery 도 재사용이 가능하게 DSL 내부에서 Parameter 를 지원해주시면 도움이 될 것 같습니다.

좋은 라이브러리 만들어주셔서 감사합니다.

cj848 commented 2 years ago

I'm glad your question has been resolved. I've looked into DetachedCriteria, but it's also Hibernate-only and I can't apply additional features like JPA Hint. Please refer to the stackoverflow answer below for the fact that DetachedCriteria and Query(TypedQuery) cannot be equivalent. https://stackoverflow.com/a/13193284/3505537

Let's close this issue. -- korean 의문이 해결되셨다니 다행입니다. DetachedCriteria 에 대해서는 검토해 보았습니다만, Hibernate 전용이기도 하고 JPA Hint 등의 추가 기능을 적용할 수 없습니다. DetachedCriteria 와 Query(TypedQuery)는 동치 될 수 없다는 사실은 아래 stackoverflow 답변을 참고해주세요. https://stackoverflow.com/a/13193284/3505537

이 이슈는 닫도록 하겠습니다.