简体   繁体   English

Micronaut jdbc 动态查询

[英]Micronaut jdbc dynamic query

I'm trying to add a dynamic filter to my queries.我正在尝试向我的查询添加动态过滤器。 I have checked that the filter itself is syntactically correct.我检查了过滤器本身在语法上是否正确。

My code is:我的代码是:

@Repository
@JdbcRepository(dialect = Dialect.POSTGRES)
interface RoomRepository extends JpaRepository<Room, Long> {
    
    @Query(SELECT * FROM person pereson_ WHERE :filter)
    Page<Person> searchPerson(String filter, Pageable pageable)
}

The error I am getting:我得到的错误:

19:39:02.376 [default-nioEventLoopGroup-1-3] TRACE io.micronaut.data.query - Binding parameter at position 1 to value AND person_.name = 'bob' with data type: STRING
19:39:02.411 [default-nioEventLoopGroup-1-3] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: SQL Error executing Query: ERROR: argument of WHERE must be type boolean, not type character varying
  Position: 158
io.micronaut.data.exceptions.DataAccessException: SQL Error executing Query: ERROR: argument of WHERE must be type boolean, not type character varying

Any ideas?有任何想法吗?

it does not work like that and btw its pretty bad style cause it makes you vunerable to sql injection.它不是那样工作的,顺便说一句,它的风格很糟糕,因为它让你容易受到 sql 注入的影响。

First create some filter class:首先创建一些过滤器 class:

data class Filter( val name: String, val value: String)

what you could to is eighter split your filter into serveral repository functions, and call them from your service depending on the set filter您可以将过滤器拆分为多个存储库功能,并根据设置的过滤器从您的服务中调用它们

@Repository
@JdbcRepository(dialect = Dialect.POSTGRES)
interface PersonRepo : PageableRepository<Person, Long> {
     findByName(name: String, pageable: Pageable): Page<Person>
     findByNameAndAgeGreaterThanEquals(name: String, age: Int, pageable: Pageable): Page<Person>
     // add some more filter methods 
}

@Singleton
class PersonService(private val repo: PersonRepo) {

  fun searchPerson(filter: List<Filter>, pageable: Pageable) : Page<Person> {
     val filters = filter.map{it.name to it.value}.toMap()
     val isNamePresent = filters.containsKey("name")
     val isAgePresent = filter.containsKey("age")
     return if(isNamePresent && !isAgePresent) {
        repo.findByName(filters["name]!!.value, pageable)
     } else if(isNamePresent && isAgePresent) {
        repo.findByNameAndAgeGreaterThanEquals(filters["name]!!.value, filters["age]!!.value, pageable)
     } else {
         Page.empty()
     }
  }
}

or you create your sql dynamically或者您动态创建 sql

@Repository
@JdbcRepository(dialect = Dialect.POSTGRES)
abstract class PersonRepo(private val jdbcOperations: JdbcOperations) : PageableRepository<Person, Long>{

    override fun searchPerson(filter: List<Filter>, pageable: Pageable): Page<Person> {

        val countSql= "SELECT COUNT(*) FROM person AS p ${filter.joinToString(" and ", "WHERE "){it.name + "= ?"}}"
        val totalAmount = jdbcOperations.prepareStatement(sql) { statement ->
            filter.forEachIndexed { i, v -> statement.setString(i+1, v.value) }
            val resultSet = statement.executeQuery()
            jdbcOperations.entityStream(resultSet, Long::class.java).findFirst().orElseGet { 0}
        }

        val sql= "SELECT * FROM person AS p ${filter.joinToString(" and ", "WHERE "){it.name + "= ?"}} SKIP ${pageable.offset} LIMIT {pageable.size}"
        val result = jdbcOperations.prepareStatement(sql) { statement ->
            filter.forEachIndexed { i, v -> statement.setString(i+1, v.value) }
            val resultSet = statement.executeQuery()
            jdbcOperations.entityStream(resultSet, Person::class.java).toList()
        }
        return Page.of(result,pageable, totalAmount)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM