与 JPA 的数据库独立字符串比较

发布于 2024-12-07 03:12:57 字数 1051 浏览 0 评论 0原文

我正在使用 JPA(Hibernate 作为提供者)和底层 MySQL 数据库。

我有一张包含德国所有街道名称的表格。每个街道名称都有一个唯一的编号。对于一项任务,我必须找出姓名的编号。为此,我编写了如下所示的 JPQL 查询。

"SELECT s FROM Strassencode s WHERE s.name = :name"

不幸的是,德国的街道名称仅在小写字母和大写字母方面有所不同,例如“Am kleinen Feld”和“Am Kleinen Feld”。显然其中一个在语法上是错误的,但作为街道名称,两种拼写都是允许的,而且两者都有不同的数字。

当我将 JPQL 查询发送到数据库时,我使用该

query.getSingleResult();

查询是因为表中的每个街道名称都是唯一的。但对于底层 MySQL 数据库,我会得到一个 NonUniqueResultException,因为 mySQL 数据库默认执行不区分大小写的比较。强制mySQL的常见方法是按照

SELECT 'abc' LIKE BINARY 'ABC';

mySQL参考手册第11.5.1章中所述编写查询,但JPQL中没有相应的关键字。

我的第一次尝试是用这样的 Annotated 注释类中的字段 name

@Column(nullable = false, columnDefinition = "varbinary(128)")

,数据库会自动进行区分大小写的比较,因为其中一个字符串是二进制的。但是当我使用这个解决方案时,当我从数据库中读取名称并将它们写入文件时,我遇到了麻烦,因为像 ä、ö、ü 这样的字母会被解释错误。

我知道,字段 name 应该获得一个 uniqueConstraint,这是我的目标之一,但这只有在数据库进行区分大小写的字符串比较时才有可能。

有没有一种解决方案,我可以配置 JPA 进行区分大小写的字符串比较,而无需手动微调数据库?

I'm working with JPA (Hibernate as provider) and an underlying MySQL database.

I have a table containing every name of streets in Germany. Every streetname has a unique number. For one task I have to find out the number of the name. To do this I wrote a JPQL-Query like the following

"SELECT s FROM Strassencode s WHERE s.name = :name"

Unfortunately there are streetnames in Germany which only differ in small and capital letters like "Am kleinen Feld" and "Am Kleinen Feld". Obviously one of them is gramatical wrong, but as a name for a street, both spellings are allowed and both of them have a different number.

When I send my JPQL-Query to the database, I'm using

query.getSingleResult();

because of the fact, that every streetname in the table is unique. But with the underlying MySQL-Database, I'll get a NonUniqueResultException, because a mySQL database is doing a case insensitive comparison by default. The common way to force mySQL is to write a query like

SELECT 'abc' LIKE BINARY 'ABC';

as discribed in chapter 11.5.1 in the mySQL Reference Manual, but there is no corresponding keyword in JPQL.

My first attempt was to annotade the field name in the class with

@Column(nullable = false, columnDefinition = "varbinary(128)")

Annotated like this, the database is automatically doing a case sensitive comparison, because one of the strings is binary. But when I use this solution, I'm running into troubles when I'm reading the names out of the databse, to write them into a file, because letters like ä, ö, ü are interpreted wrong then.

I know, that the field name should get a uniqueConstraint and it's one of my goals to do so, but this is only possible if the database will do a case sensitive string comparison.

Is there a solution, where I can configure JPA to do case sensitive string comparison without having to manually fine-tune the database?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

殤城〤 2024-12-14 03:12:57

为了保持“独立”,正如您所说的数据库和 JPA 提供程序,我将避免使用 getSingleResult() 并获取 list() 并在内存中匹配名称。可能您会得到不止 1 个,但不会是 100 个或更多。

另一种方法是将规范化的名称(修剪为小写)保存在新字段中。

To stay "independant" as you say for database and JPA provider i would avoid the getSingleResult() and fetch the list() and match in memory for the name. Probably you will get more than one but not 100 or more.

Another way could be to save the name normalised (trimmed, to lower case) in a new field.

月寒剑心 2024-12-14 03:12:57

似乎没有办法配置 JPA 来解决这个问题。但我发现,不仅可以在表级别设置排序规则,还可以为整个数据库设置排序规则,如 参考手册 12.1.10 创建数据库语法9.1.3.2。数据库字符集和排序规则

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...

create_specification:
    [DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name

我只需要创建数据库:

CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_general_cs;

有了这个,我可以在字段 name 上放置一个 uniqueConstraint 并插入“Am kleinen Feld”和“Am Kleinen Feld” “当我查询其中之一时,我只会收到一份。

不过,感谢您的帮助

Seems like there is no way in configuring JPA to solve this problem. But what I found is, that it is possible to set the collation not only on the table-level, you can also set it for the whole database as discribed in the Reference Manual 12.1.10 CREATE DATABASE SYNTAX and 9.1.3.2. Database Character Set and Collation

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...

create_specification:
    [DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name

I only had to create the database with:

CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_general_cs;

With this, I could put a uniqueConstraint on the field name and insert both "Am kleinen Feld" and "Am Kleinen Feld" and when I query for one of them, I'll only receive one.

However, thanks for the help

凡尘雨 2024-12-14 03:12:57

您还可以编写一个 SQL 查询。这就像一个普通的查询:

Query sqlQuery = session.createSqlQuery("select * from CITY where name like binary :name').addString('name', name);

请注意,代码已大致完成。

You also write a SQL query. It is like a normal query:

Query sqlQuery = session.createSqlQuery("select * from CITY where name like binary :name').addString('name', name);

Note that the code is roughly done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文