我在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? (如果长度发生变化,可能会出现维护问题)
答案 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未得到一致处理的问题。要提前解决问题,您必须更进一步
varchar2
正确处理动态尺寸如果您无法提前解决问题,那么您确实需要