bis*_*ish 5 java oracle hibernate
一些同事提出了一个问题,他们认识到查询的执行时间很慢,并且发现由于隐式类型转换而未使用索引。
该表具有kgb_uuid用于存储UUID 的属性。该列定义为,VARCHAR2并在其上具有索引以通过UUID搜索行。
实体中的相关字段定义为String。根据Hibernate文档,Hibernate应该将此字符串转换为VARCHAR2Oracle数据库上的字符串,因此应使用索引。
但这不是日志显示的情况:
[9/2/19 11:56:07:610 CEST] 00000177 SystemOut O
2019-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从MYENTITYTABLE mytab_中选择count(mytab0_.KGB_NR)作为col_0_0_,其中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
如图所示,String值的绑定VARCHAR不是not VARCHAR2,导致数据库进行隐式类型转换,而未使用索引,如OEM中所示(这是来自OEM的原始德语消息):
DasPrädikatSYS_OP_C2C(“ mytab _”。“ KGB_UUID”)=:B1,在Zeilen-ID 3 desAusführungsplansbenutzt wird中创建,并在Konvertierung des Impliziten DatentypsUuf indexerten SpalID中添加“ KGB_U”。Diese Konvertierung des impliziten Datentyps verhindert,dass der Optimizer为auf Tabelle“ MYENTITYTABLE”有效的坚果添加了知识。
它说使用了谓词SYS_OP_C2C("mytab_"."KGB_UUID")=:B1,并且它包含索引基列的隐式属性类型的KGB_UUID对话,并且这种隐式类型的对话阻止优化器有效地使用表的索引MYENTITYTABLE。
我们已经使用表上的功能索引解决了问题,但是我们仍然想知道为什么Hibernate提供的数据类型显然不是VARCHAR2。
系统:
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
}
Run Code Online (Sandbox Code Playgroud)
DAO方法
public int checkEindeutigeUUID(MyEntity myEntity) throws Exception {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> query = criteriaBuilder.createQuery(Long.class);
ParameterExpression<String> kgbUuidParam = criteriaBuilder.parameter(String.class, "kgbUuid");
ParameterExpression<EkistnutzerEntity> ekistnutzerParam = criteriaBuilder.parameter(EkistnutzerEntity.class,
"ekistnutzer");
Root<MyEntity> root = query.from(MyEntity.class);
query.select(criteriaBuilder.count(root));
query.where(criteriaBuilder.equal(root.get("kgbUuid"), kgbUuidParam),
criteriaBuilder.equal(root.get("ekistnutzer"), ekistnutzerParam));
try {
TypedQuery<Long> typedQuery = entityManager.createQuery(query);
typedQuery.setParameter("ekistnutzer", myEntity.getEkistnutzer());
typedQuery.setParameter("kgbUuid", myEntity.getKgbUuid());
return typedQuery.getSingleResult().intValue();
} catch (Exception e) {
throw e;
}
}
Run Code Online (Sandbox Code Playgroud)