Короткая версия
В настоящее время я смотрю на проблему с сопоставлениями MySQL и на то, как они влияют на набор значений (который отображается с помощью Hibernate, но это пока не должно иметь значения). Я хочу, чтобы набор строк использовал те же параметры сортировки, что и MySQL. Например. Я хочу, чтобы "foobar" и "fööbar" считались равными, но "foo bar" и "foobar" считались разными. Использование по умолчанию Collator.getInstance () (с Collator.PRIMARY сила) не работает надежно, так как есть различия ( в первую очередь пробелы). Итак, как получить Collator, который ведет себя так же, как MySQL для каждой возможной строки?
Длинная версия
Я хочу, чтобы в таблице был уникальный индекс, в котором я храню значения набора и проверяю, чтобы набор содержал только те значения, которые разрешены в БД и наоборот.
Таблица выглядит так:
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 в БД, 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
Но не работает для "foo bar" и "foobar", которые MySQL считает разными:
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!
}
Полный код для образца доступен: Скачать