在 Java 中使用 MySQL 排序规则
Posted
技术标签:
【中文标题】在 Java 中使用 MySQL 排序规则【英文标题】:Use MySQL collation in Java 【发布时间】:2010-12-04 14:30:54 【问题描述】:短版
我目前正在研究 mysql 排序规则的问题以及它们如何影响一组值(使用 Hibernate 进行映射,但现在应该不重要)。我想拥有一组使用与 MySQL 使用相同的排序规则的字符串。例如。我希望“foobar”和“fööbar”被认为是相同的,但“foo bar”和“foobar”被认为是不同的。使用默认的 Collator.getInstance()(具有 Collator.PRIMARY 强度)不能可靠地工作,因为仍然存在差异(最明显的是空格)。那么如何为每一个可能的 String 获得一个与 MySQL 表现相同的 Collator?
加长版
我希望在存储 Set 值的表上拥有唯一索引,并确保 Set 仅包含数据库中允许的值,反之亦然。
表格如下:
CREATE TABLE `MY_SET` (
`entity_id` int NOT NULL,
`value` varchar(255) NOT NULL,
UNIQUE `entity-value`(`entity_id`, `value`)
) ENGINE = InnoDB DEFAULT CHARSET=latin1 DEFAULT COLLATION=;
现在,如果我使用纯字符串和 HashSet 来保存我的值,例如如
public class MyValues
private MyEntity _myEntity;
private final HashSet<String> _values = new HashSet<String>();
可以将“foobar”和“fööbar”都添加到值集中。现在,如果 Hibernate 将 Set 刷新到 DB,MySQL 将抱怨“foobar”和“fööbar”对定义的“实体值”键重复。因此,我想我包装字符串并使用Collator 来检查字符串是否相等:
public class MyValues
private MyEntity _entity;
private final HashSet<CollatedString> _values = new HashSet<CollatedString>();
public static class CollatedString
private String _string;
private CollationKey _key;
public String getString()
return _string;
public void setString(final String string)
_string = string;
_key = getCollator().getCollationKey(_string);
@Override
public int hashCode()
return _key.hashCode();
@Override
public boolean equals(final Object obj)
if (!(obj instanceof CollatedString))
return false;
return _key.equals(((CollatedString) obj)._key);
这适用于“foobar”和“fööbar”:
final MyEntity e = new MyEntity();
final MyValues v = new MyValues();
v.setEntity(e);
v.getValues().add(new CollatedString("foobar"));
v.getValues().add(new CollatedString("fööbar"));
System.out.println("1 == " + v.getValues().size()); // prints 1 == 1
但不适用于 MySQL 认为不同的“foo bar”和“foobar”:
v.getValues().add(new CollatedString("foobar"));
v.getValues().add(new CollatedString("foo bar"));
System.out.println("2 == " + v.getValues().size()); // prints 2 == 1 (which is wrong)
基本上剩下要做的就是实现 getCollator() 方法:
public static final Collator getCollator()
// FIXME please help!
示例的完整代码可用:Download
【问题讨论】:
啊,成为真正的专家的悲哀。我只是花了两个小时在谷歌上搜索有关 MySQL 的unicode_general_ci
排序规则和 Java 的 Collator
类的惯常做法,但我找不到专门问这个问题的人:这两者有什么关系?很遗憾看到你得到 0 个答案和 cmets,但当你的专业知识远高于一般的 *** 公众时,这就是你付出的代价。 好问题,希望我能给它+10!
【参考方案1】:
我已经设法让自己发挥作用。由于我无法让内置的 Collators 做我想做的事,我决定自己实现一些东西。 I've posted my findings on my blog。基本思想是读取 MySQL 的字符集/排序规则定义文件(我的 Ubuntu 系统上的 /usr/share/mysql/charsets)。另一种方法是根据这些定义为 RuleBasedCollator 构建规则,但我决定构建自己的整理器,它的功能较少(MySQL 排序规则不能配置为区分大小写 - 它们要么是要么是不是)并且应该表现得很好。
【讨论】:
以上是关于在 Java 中使用 MySQL 排序规则的主要内容,如果未能解决你的问题,请参考以下文章