简体   繁体   English

如何强制休眠搜索具有不同模式的值?

[英]How to force hibernate to search for values with different patterns?

First of all, question is not about ignoring white spaces at the beginning or end of the strings so it is not a duplicate. 首先,问题不是关于忽略字符串开头或结尾的空格,因此它不是重复项。

I have a mobile field in database that its values are in different formats such as xxx xxx xxx, xxxxxxxxx, x xxx xxx xx etc, how can I make hibernate criteria to ignore the patterns of strings? 我在数据库中有一个移动字段,其值采用不同的格式,例如xxx xxx xxx,xxxxxxxxx,x xxx xxx xx等,如何使休眠条件忽略字符串的模式?

For example , lets say the number in database is 344 555 666 例如 ,假设数据库中的数字为344555666

 344555666  is failed 
 344 555 666 is failed 
 344 is true (first three digits that do not have space in database!)

However, there is no doubt that all numbers are provided and all aforementioned values should return 344 555 666 as their results. 但是,毫无疑问,将提供所有数字,并且所有上述值应返回344 555 666作为结果。

Another example would be as following: 另一个示例如下:

Lets say a user searches for all phone numbers that includes 12345; 假设用户搜索了所有包含12345的电话号码; then DB returns following results 12345678, 12345987 and 12345768 now I need to format these three numbers that are returned by DB before showing to the user. 然后DB返回以下结果12345678、12345987和12345768,现在我需要格式化DB返回的这三个数字,然后再显示给用户。

Code

...
private String mobile;
....

Hibernate 过冬

.add(Restrictions.ilike("user.mobile", number); 

PVR's answer is useful,but how about if in future I needed to add a new format like XXX-XXX-XXX or X-XXXX-XXXX-XXXX ? PVR的答案很有用,但是将来是否需要添加新格式,例如XXX-XXX-XXX或X-XXXX-XXXX-XXXX,该怎么办? Please also note there is only one field that user uses to enter the search value. 另请注意,用户仅可使用一个字段输入搜索值。

Try using following.. 尝试使用以下方法。

criteria.add(Restrictions.ilike(
user.mobile, number, MatchMode.ANYWHERE));

Edit : 编辑:

I meant that if the format of the no. 我的意思是,如果没有的格式。 in the database can only be one amongst XXX XXX XXXX / XXXXXXXXXX then we need to write a specific logic which checks both of the formats availability in database. 数据库中的XXX只能是XXX XXX XXXX / XXXXXXXXXX中的一个,那么我们需要编写一个特定的逻辑来检查数据库中两种格式的可用性。

number1 : in format of XXX XXX XXXX number2 : in format of XXXXXXXXXX number1:以XXX XXX XXXX的格式number2:以XXXXXXXXXX的格式

criteria.add(Restrictions.or(Restrictions.ilike(
    user.mobile, number1, MatchMode.ANYWHERE),(Restrictions.ilike(
    user.mobile, number2, MatchMode.ANYWHERE)));

Facing such problem, I usually reverse it. 面对这样的问题,我通常会扭转它。 Currently, you have in a single column of your database ( mobile ) values in different formats ( xxx xxx xxx, xxxxxxxxx, x xxx xxx xx etc. ) and it is hard to make search on that column. 当前,您在数据库( mobile )的一列中具有不同格式( xxx xxx xxx,xxxxxxxxx,x xxx xxx xx等 )的值,并且很难在该列上进行搜索。

You should still allow input of mobile numbers in all those formats, but carefully rewrite them in one single format say 12345679 before writing them in database. 您仍然应该允许以所有这些格式输入手机号码,但是在将它们写入数据库之前,请以一种单一的格式(例如12345679仔细重写它们。 This way that reformatting occurs only when inserting new records or on updates, and I assume you will have much more read accesses than write ones. 这种重新格式化的方式仅在插入新记录或更新时发生,并且我假设您将拥有比写访问更多的读访问权限。

If you allready have records in your database, you should considere using a batch to transform them in one single operation . 如果您的数据库中已经有记录,则应考虑使用批处理在单个操作中转换它们。

Once you have only one format, you can put an index on the column as it could speed select queries by orders of magnitude as soon as you have thousands of records. 一旦只有一种格式,就可以在该列上放置一个索引,因为一旦您有成千上万的记录,它就可以将选择查询的速度提高几个数量级。

When you want to do a search, allow any format for user input of what they want, and apply same transformation that you apply on insert. 当您要进行搜索时,请允许用户输入所需格式的任何格式,并应用与插入时相同的转换。 For example if a user presents 123 456 789 or 123-456-789 or any of your accepted format, in your code for search transform it in 123456789 and do you query with that value (using the index ...) 例如,如果用户显示123 456 789123-456-789或您接受的任何格式,则在您的搜索代码中将其转换为123456789然后使用该值进行查询(使用索引...)

From user point of view, you still allow he to present input as he wants, and simply the responses may come faster. 从用户的角度来看,您仍然允许他根据需要呈现输入,并且响应可能会更快。 The only drawback is that you will display not the value he entered but a standardized version of it. 唯一的缺点是您将不会显示他输入的值,而是显示它的标准化版本。

From your point of view (as the programmer) you get something simpler to write and to maintain with less stress on database. 从您(作为程序员)的角度来看,您可以编写和维护起来更简单,并且对数据库的压力较小。

did you try Projections.sqlProjection 您是否尝试过Projections.sqlProjection

You can use replace REPLACE(mobile, ' ') inside 您可以在其中使用replace REPLACE(mobile,'')

I know this is an answer that could eat up your db resources, you can test it and check if it matches your need. 我知道这是一个可能会耗尽数据库资源的答案,您可以对其进行测试并检查其是否符合您的需求。

I've done phone number formatting before, but, the solution you are looking for could be difficult, if you have to search using regex I'll construct a regex in the code and search in the db. 我之前已经做过电话号码格式化,但是,您要寻找的解决方案可能很困难,如果必须使用regex搜索,我将在代码中构造一个regex并在db中搜索。 (Oracle has regex_like function, you may want to use that instead of ilike of hibernate) (Oracle具有regex_like函数,您可能希望使用它代替ilike的休眠模式)

eg phone number from client +333 555 9999, phone number in db: +3 33 555 9999 例如,来自客户的电话号码+333 555 9999,数据库中的电话号码:+3 33555 9999

Construct the following regex based on what client sends: 根据客户端发送的内容构造以下正则表达式:

/+(\s-.)*3(\s-.)*3(\s-.)*3(\s-.)*5(\s-.)*5(\s-.)*5(\s-.)*9(\s-.)*9(\s-.)*9(\s-.)*9(\s-.\d\w)*/

What you are saying is there could be many (.) dots may (\\s) spaces many (-) hiphens in a phone number trailing with many(.\\s-\\d\\w) (eg: x234 or ext2342) 您要说的是,电话号码中可能有许多(。)点可能(\\ s)个空格,而许多(-)个henhen后面跟有许多(。\\ s- \\ d \\ w)(例如:x234或ext2342)

As per your conversation with PVR, it seems like the format of the phone number can be anything. 根据您与PVR的对话,似乎电话号码的格式可以是任何格式。 Hibernate framework is based on patterns. Hibernate框架基于模式。 It cannot handle any format on its own. 它不能自行处理任何格式。 Its advisable to not include the phone number based criteria in Hibernate. 建议不要在Hibernate中包含基于电话号码的条件。 You must execute your entire criteria query without the phone number and thereafter you must have java logic for filtering rest of the results. 您必须执行不带电话号码的整个条件查询,此后,您必须具有用于过滤其余结果的Java逻辑。

However, the best solution is make your design more solid. 但是,最好的解决方案是使您的设计更牢固。 Adding constraint on the format of the phone is the best practice. 最好在电话格式上添加约束。 You can consider adding a validation on format of phone. 您可以考虑添加电话格式的验证。

You can write your own Criterion by implementing the Criterion interface. 您可以通过实现Criterion接口来编写自己的Criterion。 In your toSqlString method just use the replace function of your database. 在您的toSqlString方法中,只需使用数据库的替换功能即可。 AFAIK replace(str, needle, replacement) is a SQL99 standard function so it should work in todays dbms. AFAIK replace(str, needle, replacement)是SQL99的标准函数,因此它应可在当今的dbms中使用。

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

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