Oracle中CHAR主键列上的休眠和填充

时间:2009-12-15 18:41:44

标签: java oracle hibernate jpa

我在Oracle中使用带有char(6)列的Hibernate时遇到了一些麻烦。这是表格的结构:

CREATE TABLE ACCEPTANCE
(
   USER_ID char(6) PRIMARY KEY NOT NULL,
   ACCEPT_DATE date
);

对于用户ID少于6个字符的记录,我可以在使用SQuirreL运行查询时选择它们而不填充用户ID。 I.E.如果存在用户ID为“abc”的记录,则以下内容返回记录。

select * from acceptance where user_id = "abc"

不幸的是,当通过Hibernate(JPA)执行select时,以下内容返回null:

em.find(Acceptance.class, "abc");

如果我填充了值,它会返回正确的记录:

em.find(Acceptance.class, "abc   ");

我正在处理的模块从用户系统的其他部分取消用户ID。是否有更好的方法让Hibernate工作,而不是在将代码用于将用户ID调整到一定长度之后再将其提供给Hibernate? (如果长度发生变化,可能会出现维护问题)

2 个答案:

答案 0 :(得分:3)

这是上帝告诉你永远不要使用CHAR()作为主键的方式: - )

但是,严重的是,由于您的user_id在您的实体中被映射为String,因此Hibernate的Oracle方言将其转换为varchar。由于Hibernate为其所有查询使用预处理语句,因此该语义会延续(与SQuirreL不同,其中值被指定为文字,因此以不同方式进行转换)。

根据Oracle type conversion rules列值,然后将其提升为varchar2并进行比较;因此你没有回复记录。

如果您无法更改基础列类型,则最佳选择可能是使用Oracle方言支持的HQL查询和rtrim()函数。

答案 1 :(得分:1)

为什么您的模块从系统的其他部分获取未填充的值?

根据我的理解,如果系统的其他部分没有改变PK,他们应该从数据库中读取6个字符并在整个过程中传递6个字符 - 这没关系。唯一的例外是生成PK时,在这种情况下可能需要填充。

您可以规避问题(通过每次必要时修剪或填充值),但不能解决您的PK未得到一致处理的问题。要提前解决问题,您必须更进一步

  • 总是从模块的其他部分收到6个字符
  • 使用varchar2正确处理动态尺寸

如果您无法提前解决问题,那么您确实需要

  • 必要时在所有地方添加修剪/填充
  • 如果你有一个
  • ,在DAO中添加修剪/填充
  • 如果有效,则在用户类型中添加修剪/填充(来自N. Hughes的建议)