사용자 지정 Hibernate Dialect 생성

Hibernate의 HQL 및 Criteria Queries로 작업하는 동안 도움이 될 PostgreSQL의 일부 기능이 누락되었습니다. 이에 대한 기본 쿼리를 작성하고 싶지 않습니다. Hibernate를 사용하고 나면 Hibernate를 고수해야 합니다. 오른쪽?

Hibernate의 기본 Postgres 방언에서 내가 놓친 기능 중 하나는 similarity 함수였는데, 이 함수는 두 문자열이 0에서 1 스케일로 어떻게 다른지 반환합니다. 따라서 HQL 또는 기준 쿼리에서 similarity 기능을 사용할 수 있도록 자체 Hibernate 방언을 생성하는 방법을 살펴보겠습니다.

방언 수업



먼저 방언으로 클래스를 만들어 봅시다. Kotlin btw를 사용하고 있습니다. 😎

package io.tolgee.dialects.postgres

import org.hibernate.NullPrecedence
import org.hibernate.dialect.PostgreSQL10Dialect
import org.hibernate.dialect.function.SQLFunction
import org.hibernate.engine.spi.Mapping
import org.hibernate.engine.spi.SessionFactoryImplementor
import org.hibernate.type.FloatType
import org.hibernate.type.Type

class CustomPostgreSQLDialect : PostgreSQL10Dialect() {
  init {
    registerFunction(
      "similarity",
      object : SQLFunction {
        override fun hasArguments(): Boolean = true

        override fun hasParenthesesIfNoArguments() = false

        override fun getReturnType(firstArgumentType: Type?, mapping: Mapping?) = FloatType()

        override fun render(
          firstArgumentType: Type,
          arguments: MutableList<Any?>,
          factory: SessionFactoryImplementor
        ): String {
          return "similarity(${arguments[0]}, ${arguments[1]})"
        }
      }
    )
  }
}


간단하죠? 생성자에서 우리는 registerFunction 메서드를 호출하여 함수 이름 매개변수와 개체 구현SQLFunction 인터페이스를 수락합니다. 아마도 나중에 내 CustomPostgreSQLDialect가 커질 때 이것을 별도의 클래스로 추출할 것이지만 지금은 이것으로 괜찮습니다.

우리는 인터페이스를 구현하고 있기 때문에 재정의해야 하는 메서드가 거의 없습니다. 그들의 이름은 꽤 자명합니다. 그것은 Hibernate에게
  • 함수에 인수가 있음
  • Float 반환 유형이 있음
  • HQL 또는 CriteriaQuery가 SQL로 변환되면 similarity(1st argument, 2nd argument)와 같이 렌더링되어야 합니다.
  • hasParenthesesIfNoArguments는 함수가 인수 없이 작동할 수 없기 때문에 의미가 없으므로 false로 설정했습니다.

    방언 사용



    방언을 활성화하는 것은 Hibernate propdialect를 방언의 절대 클래스 이름으로 설정하는 것만큼 간단합니다.

    저는 Spring Boot를 사용하고 있기 때문에 application.yaml 에 이것을 가지고 있습니다.

    spring:
      jpa:
        properties:
          hibernate:
            dialect: io.tolgee.dialects.postgres.CustomPostgreSQLDialect
    


    테스트 시간!





    package io.tolgee.dialects.postgres
    
    import io.tolgee.model.UserAccount
    import io.tolgee.testing.assertions.Assertions.assertThat
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests
    import org.testng.annotations.Test
    import javax.persistence.EntityManager
    
    
    @SpringBootTest
    class CustomPostgreSQLDialectTest: AbstractTransactionalTestNGSpringContextTests() {
    
      @Autowired
      lateinit var entityManager: EntityManager
    
      @Test
      fun `similarity function works`(){
        // Hibernate queries doesn't work without FROM clause, so we have 
        // to create a dummy entity to select from
        entityManager.persist(UserAccount(username = "aaa", password = "aaaa", name = "aaaaa"))
        val query = entityManager.createQuery(
          "select similarity('I am so funny!', 'You are so funny!') from UserAccount"
        )
        assertThat(query.singleResult).isEqualTo(0.47619048f)
      }
    }
    


    TL; DR


  • 데이터베이스 시스템의 고급 기능을 사용해야 하는 경우 고유한 Hibernate 방언을 생성합니다
  • .
  • 다른 방언을 확장하고 필요한 기능을 추가하기만 하면 됩니다.



  • Tolgee는 소프트웨어 현지화를 위한 오픈 소스 솔루션입니다. 개발자의 시간을 절약해 줍니다. Tolgee.io로 이동하여 즐기십시오!

    좋은 웹페이지 즐겨찾기