mysql - QueryDSL:比较数组

标签 mysql hibernate kotlin querydsl

我在比较 QueryDSL 数组时遇到问题。问题是 QueryDSL 中缺少对字节数组的比较,因为 ArrayPath 扩展了 SimpleExpression,它只有 eq、ne、in、isNull 等方法...

使用 Kotlin、Hibernate 5.2、QueryDSL 4.1.4、MySQL 5.7

拥有 Hibernate ebmeddable 对象 IpAddress

@Embeddable
class IpAddress(
        var ipAddressBinary: ByteArray
) 

在 DB 中映射到类型 VARBINARY(4)(对于 IPv4 地址, future 计划支持 IPv6)。我以二进制形式存储 IP 地址,以便在范围内进行搜索。

我想创建 kotlin 扩展函数来支持嵌入对象上的 goe 和 loe 函数

到目前为止我想出了这个:

fun ArrayPath<ByteArray, Byte>.goe(ipBytes: ByteArray): BooleanExpression {
  return Expressions.booleanOperation(Ops.GOE, ConstantImpl.create(ipBytes))
}

fun QIpAddress.goe(ipAddressStr: String): BooleanExpression {
  val ipBytes = MapperUtils.IPv4.normalizedToBytes(ipAddressStr)
  return this.ipAddressBinary.goe(ipBytes)
}

但是打电话

query.where(QBlackListRecord.blackListRecord.startAddress.goe(someByteArrayRepresentingIpAddress))

导致异常:

 [exec-10]java.lang.IndexOutOfBoundsException: index (1) must be less than size (1)
at com.google.common.base.Preconditions.checkElementIndex(Preconditions.java:310)
at com.google.common.base.Preconditions.checkElementIndex(Preconditions.java:292)
at com.google.common.collect.SingletonImmutableList.get(SingletonImmutableList.java:45)
at com.querydsl.core.types.Template$ByIndex.convert(Template.java:190)
at com.querydsl.core.support.SerializerBase.visitOperation(SerializerBase.java:256)
at com.querydsl.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:426)
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:231)
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83)
at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
at com.querydsl.core.support.SerializerBase.visitOperation(SerializerBase.java:267)
at com.querydsl.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:437)
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:231)
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83)
at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
at com.querydsl.jpa.JPQLSerializer.serialize(JPQLSerializer.java:220)
at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:60)
at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:50)
at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:98)
at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:94)
at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:201)
at org.springframework.data.jpa.repository.support.QuerydslJpaRepository.findAll(QuerydslJpaRepository.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:629)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:593)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy144.findAll(Unknown Source)

我不确定我处理此事的方法是否正确。是否有其他方法可以在 QueryDSL 中比较字节数组,从而使用简单的比较运算符生成简单的 SQL?

我所需要的只是生成这样的 SQL

select *
from black_list_record
where start_ip_address_binary >= @binary_value

或者像这样

select *
from black_list_record
where start_ip_address_binary >= inet6_aton('10.20.0.1')

最佳答案

错误是由函数引起的

fun ArrayPath<ByteArray, Byte>.goe(ipBytes: ByteArray): BooleanExpression {
  return Expressions.booleanOperation(Ops.GOE, ConstantImpl.create(ipBytes))
}

应该是这样的

fun ArrayPath<ByteArray, Byte>.goe(ipBytes: ByteArray): BooleanExpression {
  return Expressions.booleanOperation(Ops.GOE, this, ConstantImpl.create(ipBytes))
}

我没有为 GOE 操作传递“this”参数,该操作需要两个参数,因为其模板为 {0} >= {1}。这就是全部...

如果您不使用 Kotlin,而是使用 Java,则可以使用 QueryDSL 内置方法委托(delegate) - http://www.querydsl.com/static/querydsl/4.2.1/reference/html_single/#d0e2474

关于mysql - QueryDSL:比较数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52035137/

相关文章:

php - 在php-mysql中,while语句中的变量$row ['disease_$lang2' ] 应该怎么写?

mysql - 如何将我的 mysql 数据库从 phpmyadmin 推送到 heroku 的 cleardb?

php - 插入数据库中具有两位小数的千位数的格式

java - Jasypt - 使用不同的加密器进行加密和解密

Kotlin 自定义作用域函数返回类型未按预期运行

python - 如何通过避免行名称等来仅打印数据库中的值(在 Django 中)

java - JPA:如何处理多个实体

java - 外键正在更新为空

android - 如何修复由目的地引起的膨胀错误不是此 NavGraph 的直接子级

Android Room with a View - Kotlin Gradle DSL 方法未找到 : 'kapt()'