跳转至

Vertica 集成 Hibernate:连接指南

关于 Vertica 连接指南

Vertica 连接指南提供将第三方合作伙伴产品连接到 Vertica 的基本说明。连接指南基于我们在特定版本的 Vertica 和合作伙伴产品上的测试。

Vertica 与 Hibernate:软件版本

本文档基于 Hibernate 5.4.1 与 Vertica 9.2 的测试结果。

要求

使用 Hibernate 与 Vertica 需要:

  • JDK 8.0 或更高版本
  • VerticaDialect.jar
  • Hibernate 5 或更高版本
  • Vertica 客户端 9.0 或更高版本
  • Vertica 服务器 9.0 或更高版本

Hibernate 概述

Hibernate 是 Java 编程语言的 ORM(对象-关系映射)工具。Hibernate 提供了将面向对象的领域模型映射到关系数据库的框架。Hibernate 是免费的开源软件。

使用 VerticaDialect 与 Hibernate

Hibernate 方言(dialect)指定底层数据库的 SQL 方言,以便 Hibernate 生成适当的 SQL 语句。

本文档引导您完成创建基于控制台�� Hibernate 应用程序的过程。使用此应用程序通过 VerticaDialect 建立到 Vertica 数据库的连接,并执行所有 CRUD 操作,包括插入、删除和简单 SQL 语句。

本文档使用以下 SQL 语句作为示例:

SELECT class_desc, Item_DESC, sum(units_received)
FROM lookup_item, Inventory_orders
WHERE lookup_item.item_nbr = Inventory_ORDERS.item_id
GROUP BY class_desc, Item_DESC
ORDER BY class_desc, Item_DESC

搭建环境

下载和安装 Hibernate

从 https://sourceforge.net/projects/hibernate/files/hibernate-orm/ 下载 Hibernate 发行版,按照 Hibernate 安装向导的说明安装。

下载和安装 JDK

按照 Oracle 网站上的说明下载和安装 Java Development Kit (JDK)。

下载 Vertica 客户端驱动

  1. 导航至 Vertica 网站上的 Client Drivers 页面
  2. 下载 JDBC 驱动程序包(注意:有关客户端和服务器兼容性的详细信息,请参阅 Vertica 文档)
  3. 将 Vertica JDBC .jar 文件复制到客户端外部库目录

下载 VerticaDialect.jar

  1. 右键点击此链接
  2. 选择 Save link as... 将 VerticaDialect.jar 保存到您的计算机
  3. 将 VerticaDialect.jar 复制到客户端外部库目录

创建 Hibernate 映射文件

必须创建 Hibernate 映射文件,以便 Hibernate 可以加载和存储持久化类的对象。映射文件告诉 Hibernate 将哪些数据库表和列映射到 Java 类。

在本示例中,将为两个表创建类对象映射:Inventory_Orders 表和 Lookup_Item 表。还包括两个对象之间的关联。

InventoryOrders.hbm.xml

<!-- InventoryOrders.hbm.xml 映射 Inventory_Orders 表到 InventoryOrders 类 -->

Item.hbm.xml

<!-- Item.hbm.xml 映射 Lookup_Item 表到 Item 类 -->

创建 Java 持久化类

InventoryOrders.java

package com.sample;
public class InventoryOrders {
  float item_id;
  float units_received;

  public float getItem_id() { return item_id; }
  public void setItem_id(float item_id) { this.item_id = item_id; }
  public float getUnits_received() { return units_received; }
  public void setUnits_received(float units_received) { this.units_received = units_received; }
}

Item.java

package com.sample;
public class Item {
  float item_nbr;
  String class_desc;
  String item_desc;
  InventoryOrders inventoryorders;

  public InventoryOrders getInventoryorders() { return inventoryorders; }
  public void setInventoryorders(InventoryOrders inventoryorders) { this.inventoryorders = inventoryorders; }
  public float getItem_nbr() { return item_nbr; }
  public void setItem_nbr(float item_nbr) { this.item_nbr = item_nbr; }
  public String getClass_desc() { return class_desc; }
  public void setClass_desc(String class_desc) { this.class_desc = class_desc; }
  public String getItem_desc() { return item_desc; }
  public void setItem_desc(String item_desc) { this.item_desc = item_desc; }
}

创建配置文件条目

Hibernate 配置文件 (hibernate.cfg.xml)

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">com.vertica.jdbc.Driver</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.connection.url">jdbc:vertica://<host>:<port>/<database></property>
    <property name="hibernate.connection.username">dbadmin</property>
    <property name="hibernate.dialect">org.hibernate.dialect.VerticaDialect</property>
    <property name="hibernate.show_sql">true</property>
  </session-factory>
</hibernate-configuration>

创建主类

package com.sample;
import java.util.Iterator;
import org.hibernate.Query;
import org.hibernate.Session;

public class TestHibernate {
  public static void main(String[] args) {
    Session session = SessionFactoryUtil.getSessionFactory().openSession();
    session.beginTransaction();
    queryInventory(session);
    System.out.println("done");
  }

  private static void queryInventory(Session session) {
    Query query = session.createQuery(
      "select a.class_desc, a.item_desc, sum(b.units_received) " +
      "from Item a, InventoryOrders b " +
      "where a.item_nbr = b.item_id " +
      "group by a.class_desc, a.item_desc " +
      "order by a.class_desc, a.item_desc");
    System.out.println("Class Desc \t\t Item Desc \t\t Total Unit");
    for (Iterator it = query.iterate(); it.hasNext();) {
      Object[] row = (Object[]) it.next();
      System.out.print(row[0]);
      System.out.print("\t\t" + row[1]);
      System.out.print("\t\t" + row[2]);
      System.out.println();
    }
    session.close();
  }
}

构建和运行 Hibernate 应用程序

构建和运行命令

使用以下命令编译和运行(需要将所有依赖 jar 添加到 classpath):

java -cp "C:\Hibernate\lib\antlr-2.7.7.jar";"C:\Hibernate\lib\classmate-1.3.4.jar";
"C:\Hibernate\lib\commons-collections-3.2.1.jar";"C:\Hibernate\lib\dom4j-2.1.1.jar";
"C:\Hibernate\lib\byte-buddy-1.9.5.jar";"C:\Hibernate\lib\FastInfoset-1.2.15.jar";
"C:\Hibernate\lib\hibernate-commons-annotations-5.1.0.Final.jar";
"C:\Hibernate\lib\hibernate-jpa-2.1-api-1.0.0.Final.jar";
"C:\Hibernate\lib\jandex-2.0.5.Final.jar";"C:\Hibernate\lib\javassist-3.24.0.GA.jar";
"C:\Hibernate\lib\jboss-logging-3.3.2.Final.jar";
"C:\Hibernate\lib\jboss-transaction-api_1.2_spec-1.1.1.Final.jar";
"C:\Hibernate\lib\slf4j-api-1.5.8.jar";"C:\Hibernate\lib\VerticaDialect.jar";
"C:\Hibernate\lib\vertica-jdbc-9.2.0-0.jar";"C:\Hibernate\lib\hibernate-core-5.4.1.Final.jar";
"C:\Hibernate\lib\istack-commons-runtime-3.0.7.jar";
"C:\Hibernate\lib\javax.activation-api-1.2.0.jar";
"C:\Hibernate\lib\javax.persistence-api-2.2.jar";"C:\Hibernate\lib\jaxb-api-2.3.1.jar";
"C:\Hibernate\lib\jaxb-runtime-2.3.1.jar";"C:\Hibernate\lib\stax-ex-1.8.jar";
"C:\Hibernate\lib\txw2-2.3.1.jar" com.sample.TestHibernate

使用 VerticaDialect 的自定义函数

要添加 Hibernate 4 支持的 VerticaDialect 自定义函数,创建一个扩展 VerticaDialect 的 Java 类并注册函数:

package org.hibernate.dialect;

import org.hibernate.dialect.VerticaDialect;
import org.hibernate.dialect.function.NvlFunction;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StandardBasicTypes;

public class VerticaDialectCustom extends VerticaDialect {
  public VerticaDialectCustom() {
    super();
    registerFunctions();
  }

  protected void registerFunctions() {
    registerFunction("substring", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
    registerFunction("bit_length", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "vsize(?1)*8"));
    registerFunction("coalesce", new NvlFunction());
  }
}

使用 CustomVerticaDialect 的 hibernate.cfg.xml:

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">com.vertica.jdbc.Driver</property>
    <property name="hibernate.dialect">org.hibernate.dialect.CustomVerticaDialect</property>
    ...
  </session-factory>
</hibernate-configuration>

Hibernate 批处理操作

Hibernate 批量插入将大量结果集作为一批记录上传到 Vertica 数据库,而不是每次插入单行时都上传。

在配置中设置批处理大小:

<property name="hibernate.jdbc.batch_size">1000</property>

batch_size 的值取决于对象大小和总结果集数量。

已知限制

由于 Vertica 是 OLAP 数据库,不完全遵循 OLTP 数据库的所有特性,Hibernate 不维护主键的唯一性。

尝试以下操作时 Hibernate 会报错:

  • 插入重复记录到主键表org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session

  • 表包含重复数据时删除记录:Hibernate 执行基于主键的 DELETE,但表中可能存在重复数据

注意: 可以通过使用 Vertica 9.x 引入的 Constraint Enforcement Parameters 来避免此问题。启用此参数后,Vertica 强制主键和唯一键约束,Hibernate 可以正常工作。

更多信息

  • Hibernate
  • Vertica Community Edition
  • Vertica User Community
  • Vertica Documentation

截图

SampleOutput


原文来源:https://www.vertica.com/kb/HPE-Vertica-Integration-with-Hibernate-Connection-Guide/Content/Partner/HPE-Vertica-Integration-with-Hibernate-Connection-Guide.htm