为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 Hibernate 避免从 VARCHAR 到 VARCHAR2 的隐式类型转换?

如何使用 Hibernate 避免从 VARCHAR 到 VARCHAR2 的隐式类型转换?

MMTTMM 2023-07-28 15:23:40
一些同事提出了一个问题,他们发现查询执行时间很慢,并且发现由于隐式类型转换而未使用索引。kgb_uuid该表有一个用于存储 UUID 的属性。该列被定义为VARCHAR2并具有一个索引,用于通过 UUID 搜索行。实体中的相关字段定义为String。根据 Hibernate 文档,Hibernate 应该将此字符串转换为VARCHAR2Oracle 数据库,因此应该使用索引。但事实并非如此,如日志所示:[9/2/19 11:56:07:610 CEST] 00000177 SystemOut O2019-09-02T11:56:07,610 TRACE [ebContainer : 3] ibebcTraceInterceptor;log;;41 - 类 [MyDAO] 中的入口方法 [checkEindeutigeUUID]带参数 (MyEntity@b14745f9)[9/2/19 11:56:07:688 CEST] 00000177 SQL Z org.hibernate.engine.jdbc.spi.SqlStatementLogger logStatement 选择 count(mytab0_.KGB_NR) as col_0_0_ from MYENTITYTABLE mytab_ where mytab_.KGB_UUID=?和 mytab_.EKN_NR=?[9/2/19 11:56:07:688 CEST] 00000177 BasicBinder Z org.hibernate.type.descriptor.sql.BasicBinder 绑定参数 [1] 作为 [VARCHAR] - 795BF3B98D879358E0531C03A90ABF0A [9/2/19 11:56 :07:688 CEST] 00000177 BasicBinder Z org.hibernate.type.descriptor.sql.BasicBinder 绑定绑定参数 [2] 作为 [BIGINT] - 1正如所见,字符串值被绑定为VARCHARnot as VARCHAR2,导致数据库进行隐式类型转换并且不使用索引,如 OEM 中所示(这是来自 OEM 的原始德语消息):执行计划的行 ID 3 中使用的谓词 SYS_OP_C2C("mytab_"."KGB_UUID")=:B1 包含索引列“KGB_UUID”上的隐式数据类型转换。这种隐式数据类型转换会阻止优化器有效地使用表“MYENTITYTABLE”上的索引。它表示使用了谓词SYS_OP_C2C("mytab_"."KGB_UUID")=:B1,并且它包含索引基列的隐式属性类型的对话KGB_UUID,并且该隐式类型的对话阻止优化器有效地使用表的索引MYENTITYTABLE。我们已经解决了在表上使用功能索引的问题,但我们仍然想知道为什么 Hibernate 提供了一种显然不是VARCHAR2.系统:Hibernate 4.2.21 与 Hibernate Dialect Oracle10g(根据文档最多兼容 12 个)Oracle 12.2(现在不完全是,我认为是12.2,但也许只是12.1)Hibernate 版本无法升级,因为它是可与 JPA 2.0 一起使用的最后一个版本,JPA 2.0 是 Websphere Process Server 8.5 支持的 JavaEE 6 的一部分。(简称)实体@Entity@Table(name = "MYENTITYTABLE")public class MyEntity implements Serializable {  private static final long serialVersionUID = 1L;  @Id  // out commented the sequence generator   @Column(name="KGB_NR")  private long kgbNr;  @Column(name="KGB_UUID")  private String kgbUuid; // <<== DEFINED AS STRING!  //bi-directional many-to-one association to Ekistnutzer  @ManyToOne  @JoinColumn(name="EKN_NR")  private EkistnutzerEntity ekistnutzer;  // Other attributes not related in problem} 
查看完整描述

1 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

最简单的方法是扩展默认值StringType并覆盖sqlType属性,并通过注释向实体属性提供新的 Hibernate 类型@Type

该映射很可能VARCHAR2是通过 Oracle Hibernate Dialect 实现的,因此您不应该覆盖默认的 Dialect 映射,因为可能存在正确使用VARCHAR2.

因此,自定义 Hibernate 类型为您提供了控制权,并允许您仅将其用于列VARCHAR


查看完整回答
反对 回复 2023-07-28
  • 1 回答
  • 0 关注
  • 95 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信