简体   繁体   English

如何在 Spring Data JPA 查询中将字符串转换为 IP 地址

[英]How to cast string to IP Address in Spring Data JPA Query

I have a table that contains ranges of IP addresses with starting and ending values in their own columns.我有一个表,其中包含 IP 地址范围,在它们自己的列中具有起始值和结束值。 These columns are of type varchar.这些列的类型为 varchar。 I need to query the database to get rows for which the range covers that IP Address.我需要查询数据库以获取范围涵盖该 IP 地址的行。

Here is my query that works perfectly fine with PGSQL:这是我的查询与 PGSQL 完美配合:

select * from ip_whitelist iw where iw.ip_address::inet <= '1.1.1.54'::inet and iw.ip_address_end::inet >= '1.1.1.54'::inet

1.1.1.54 is just a dummy value here that will be replaced by a variable in my JPA query: 1.1.1.54 在这里只是一个虚拟值,它将被我的 JPA 查询中的一个变量替换:

Here's how I'm trying to run this query via JPA Repository:这是我尝试通过 JPA 存储库运行此查询的方式:

@Query("select ip from AllowedIp ip where CAST(ip.ipAddress AS inet) <= CAST((?1) AS inet) and CAST(ip.ipAddressEnd AS inet) >= CAST((?1) AS inet)")
List<AllowedIp> findDuplicatesByIP(String ipAddress);

My problem is I need to cast the ipAddress and ipAddressEnd columns to inet within this JPA query so I can use the <= and >= operators to search if a range already covers the given IP.我的问题是我需要在此 JPA 查询中将ipAddressipAddressEnd列转换为inet ,以便我可以使用 <= 和 >= 运算符来搜索范围是否已经涵盖给定的 IP。 The JPA query mentioned above is throwing an error when I try to start my Tomcat application.当我尝试启动 Tomcat 应用程序时,上面提到的 JPA 查询抛出错误。 Here's the stack trace:这是堆栈跟踪:

    Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: Could not resolve requested type for CAST : inet [select ip from com.uxl.dataobjects.domain.AllowedIp ip where CAST(ip.ipAddress AS inet) <= CAST((?1) AS inet) and CAST(ip.ipAddressEnd AS inet) >= CAST((?1) AS inet)]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:331)
        at sun.reflect.GeneratedMethodAccessor69.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:344)
        at com.sun.proxy.$Proxy152.createQuery(Unknown Source)
        at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:86)
        ... 101 more
    Caused by: org.hibernate.QueryException: Could not resolve requested type for CAST : inet [select ip from com.uxl.dataobjects.domain.AllowedIp ip where CAST(ip.ipAddress AS inet) <= CAST((?1) AS inet) and CAST(ip.ipAddressEnd AS inet) >= CAST((?1) AS inet)]
        at org.hibernate.QueryException.generateQueryException(QueryException.java:137)
        at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:120)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:234)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
        at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
        at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1836)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328)
        ... 107 more
    Caused by: org.hibernate.QueryException: Could not resolve requested type for CAST : inet
        at org.hibernate.hql.internal.ast.tree.CastFunctionNode.resolve(CastFunctionNode.java:87)
        at org.hibernate.hql.internal.ast.HqlSqlWalker.processCastFunction(HqlSqlWalker.java:1097)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.functionCall(HqlSqlBaseWalker.java:2748)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1342)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4686)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4252)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2104)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2029)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:796)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:597)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
        ... 115 more

Possible Solutions I've explored that didn't work out:我探索过但没有奏效的可能解决方案:

  1. Cast the String IP to InetAddress data type in java instead.将字符串 IP 转换为 java 中的 InetAddress 数据类型。 This cannot work because the table columns are still in string type so they will still need to be cast in order to use the operators.这是行不通的,因为表列仍为字符串类型,因此仍需要对其进行强制转换才能使用运算符。
  2. Get all rows and filter in Java.在 Java 中获取所有行和过滤器。 While this may work, this seems to be an impractical solution, not to mention bad practice.虽然这可能有效,但这似乎是一个不切实际的解决方案,更不用说糟糕的做法了。
  3. I found Vlad Mihalcea's guide to using custom hibernate types and inlcuded the package in my project.我找到了Vlad Mihalcea 的使用自定义休眠类型的指南,并在我的项目中包含了该包。 However, I can't figure how to use it for casting in my query, because its primarily used in entities where the column data type is Inet.但是,我无法弄清楚如何在我的查询中使用它进行转换,因为它主要用于列数据类型为 Inet 的实体。 In my case, columns in the table are of type varchar.就我而言,表中的列是 varchar 类型。

Can someone please tell me what I'm doing wrong?有人可以告诉我我做错了什么吗? Any suggestion on how I can get this to run will be greatly appreciated.任何关于我如何让它运行的建议将不胜感激。

EDIT 1: Added another possible solution I've tried.编辑 1:添加了我尝试过的另一个可能的解决方案。

After some research, I have realized the answer was there all along.经过一番研究,我意识到答案一直存在。 This is not an ideal solution, but good enough for now until Hibernate natively supports inet data type.这不是一个理想的解决方案,但在 Hibernate 本身支持 inet 数据类型之前,现在已经足够了。

The solution is to use nativeQuery = true parameter in @Query.解决方案是在@Query 中使用nativeQuery = true参数。 So the final query becomes:所以最终的查询变成:

@Query(nativeQuery = true, value = "select * from ip_whitelist where CAST(ip_address AS inet) <= CAST((?1) AS inet) and CAST(ip_address_end AS inet) >= CAST((?1) AS inet)")

The built-in cidr and inet types will do what you want and provide suitable operators and for more details regarding cast in postgres use this link内置的 cidr 和 inet 类型会做你想做的事并提供合适的操作符,有关 postgres 中的转换的更多详细信息,请使用此链接

SELECT '192.168.1.19'::inet << '192.168.1.0/24'::cidr 

The above query helps you give ip address directly and if needed to cast it then make use of the below links that helps in those conversions上面的查询可以帮助您直接提供 ip 地址,如果需要进行转换,请使用以下有助于这些转换的链接

https://www.postgresql.org/message-id/Pine.LNX.4.20.0107211126100.4270-100000@Larry.bks https://www.postgresql.org/message-id/Pine.LNX.4.20.0107211126100.4270-100000@Larry.bks

https://www.postgresql.org/message-id/F28A2B83DFE0D411A7B3006097487147468FDB%40sv7007.scania.se https://www.postgresql.org/message-id/F28A2B83DFE0D411A7B3006097487147468FDB%40sv7007.scania.se

https://www.postgresql.org/docs/9.1/datatype-net-types.html#:~:text=PostgreSQL%20offers%20data%20types%20to,functions%20(see%20Section%209.12) . https://www.postgresql.org/docs/9.1/datatype-net-types.html#:~:text=PostgreSQL%20offers%20data%20types%20to,functions%20(见%20Section%209.12)

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

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