Hibernate版本升级bug解决全过程

文章讲述了作者在将Hibernate从5.x升级到6.x时,遇到查询时的错误,发现新版本中Hibernate倾向于使用实体类属性名称作为SQL列名,导致与旧版不同,解决方法是调整SQL语句的列名与实体类属性一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:最近在升级hibernate的版本,由hibernate5.x升级至hibernate6.x,记录下在查询数据时遇到的问题。

1.执行如下代码:

2.报错现象:

org.hibernate.query.sqm.InterpretationException: Error interpreting query [from IntentModel a where id=1 order by a.create_time ]; this may indicate a semantic (user query) problem or a bug in the parser [from IntentModel a where id=1 order by a.create_time ]

3.问题分析:

(1)根据错误信息可以确定表【IntentModel】是真实存在的,查看表结构,确实存在id和create_time列,所以可以明确不是表结构的问题。

(2)回看代码,就是一个根据条件查询数据的SQL,查询条件有两个,拆开一个一个执行,发现问题问题出现order by a.create_time语句上。

(3)由(2)中的结论得知create_time也是存在的,所以怀疑是不是实体类上的@Column(name = "create_time")是不是没生效,但很快又被我推翻了,如果注解没生效,那么表结构中应该没有create_time列,陷入了沉思~~~~

(4)拆开查询条件执行时,发现id列作为查询条件时都可以执行成功,create_time列作为查询条件确抛异常,所以很明确就是create_time的问题,我又试了试其他的列作为查询条件是否能成功,惊喜马上就要出现了,发现SQL中的列名和实体类属性名称一模一样的就可以成功,反之不一样的就会抛异常,大胆怀疑就是SQL中写的列名和数据库中的列名映射出了问题,可明明都是create_time,为啥会这样呀,于是我将SQL中的列名改成了属性名createTime【不是@Column(name = "create_time")中的name】,查询成功。

(5)问题解决后,我查询了相关资料后,发现hibernate5.x升级到hibernate6.x版本之后,SQL语句也发生了变化。

4.总结如下:

Hibernate 5.x版本中,使用@Column注解时,Hibernate会使用@Column注解的name属性作为列名来创建SQL查询。而在Hibernate 6.x版本中,Hibernate更倾向于使用实体类的属性名称作为SQL查询的列名。

这种变化可能是为了提高Hibernate与实体类之间的映射一致性,以及提高代码的可读性。Hibernate 6.x版本更加强调与JPA规范的一致性,因此在处理列名时,它更倾向于使用实体类的属性名称。

扩展

Hibernate 6.x对命名策略的调整:在Hibernate 6.x中,命名策略(naming strategy)的实现和应用有所调整。尽管你可能在实体类的属性上使用@Column(name = "column_name")来指定数据库列名,但Hibernate在构建HQL或原生SQL查询时,会根据配置的命名策略来转换实体属性名。默认情况下,Hibernate会将实体类中的Java命名风格(驼峰命名法)转换为数据库风格(下划线分隔的小写命名)。

HQL与SQL查询的差异:在使用HQL(Hibernate Query Language)查询时,你通常会直接引用实体类属性名,而Hibernate会自动处理属性名与数据库列名之间的映射关系。但在使用原生SQL查询时,你直接在查询语句中引用数据库列名,因此需要使用数据库中的实际列名,这可能与实体类属性名不一致。

在HQL(Hibernate Query Language)查询中,直接使用实体类的属性名是标准做法,因为Hibernate会根据配置的命名策略自动处理属性名到数据库列名的映射。这意味着在HQL中使用firstName而不是first_name是推荐的,因为Hibernate会自动将驼峰命名的Java属性名转换为数据库中相应的下划线分隔的小写列名。如果Hibernate的命名策略被配置为将firstName转换为first_name,直接使用first_name可能与命名策略的自动转换逻辑冲突,导致Hibernate无法正确解析查询。

使用SQL查询:如果你的查询需求无法通过HQL表达,或者你确实需要直接操作数据库列名,可以考虑使用原生SQL查询。在Hibernate中,你可以通过createSQLQuery方法来执行原生SQL查询,这样就可以直接使用first_name数据库列名。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值