Home > Blockchain >  Annotation argument with variable
Annotation argument with variable

Time:10-13

In our Spring project I want to convert Java repository to Kotlin. Repository is an interface with methods and annotations which contains database query as a argument. There are several methods, but the most complex and longest part of the query is repeated. In Java, we inserted a string into the query as a variable.

Current solution in Kotlin cannot compile because 'an annotation argument must be a compile-time constant'.

What is the best way to handle this?

interface PlaceRepository : JpaRepository<Place, UUID>, JpaSpecificationExecutor<Place> {

    val HAVERSINE_FORMULA: String
        get() =
            """
                (6371 * acos(cos(radians(CAST(CAST(:latitude AS string) AS double)))
                * cos(radians(p.gpsLatitude)) * cos(radians(p.gpsLongitude) - radians(CAST(CAST(:longitude AS string) AS double)))
                  sin(radians(CAST(CAST(:latitude AS string) AS double))) * sin(radians(p.gpsLatitude))))
            """

    @Query("""
        SELECT p AS place,
             $HAVERSINE_FORMULA AS distance
        FROM Place p
        WHERE p.code = :code
    """)
    fun findByCode(
        code: String,
        latitude: Double,
        longitude: Double
    ): Optional<PlaceWithDistanceDTO>
}

Thank you

CodePudding user response:

You can try using a companion object as follows:

interface PlaceRepository : JpaRepository<Place, UUID>, JpaSpecificationExecutor<Place> {

    companion object {
        private const val HAVERSINE_FORMULA =
            """
                (6371 * acos(cos(radians(CAST(CAST(:latitude AS string) AS double)))
                * cos(radians(p.gpsLatitude)) * cos(radians(p.gpsLongitude) - radians(CAST(CAST(:longitude AS string) AS double)))
                  sin(radians(CAST(CAST(:latitude AS string) AS double))) * sin(radians(p.gpsLatitude))))
            """
    }

    @Query("""
        SELECT p AS place,
             $HAVERSINE_FORMULA AS distance
        FROM Place p
        WHERE p.code = :code
    """)
    fun findByCode(
        code: String,
        latitude: Double,
        longitude: Double
    ): Optional<PlaceWithDistanceDTO>
}
  • Related