本文介紹了如何通過Hibernate使用Tablestore的JDBC驅動來快速存取Tablestore。

背景資訊

Hibernate是面向Java環境的對象/關係映射(ORM)解決方案,主要負責從Java類到資料庫表的映射以及從Java資料類型到SQL資料類型的映射,同時還支援資料查詢。使用Hibernate能有效減少在SQL和JDBC中手動處理資料所花費的時間。更多資訊,請參見Hibernate官網文檔

注意事項

目前支援使用SQL查詢功能的地區有華東1(杭州)、華東2(上海)、華北2(北京)、華北3(張家口)、華南1(深圳)和新加坡。

前提條件

  • 如果要使用RAM使用者進行操作,請確保已建立RAM使用者,並為RAM使用者授予所有SQL操作許可權,即在自訂權限原則中配置"Action": "ots:SQL*"。具體操作,請參見t1985835.html#section_6hb_cr0_iv9
  • 已擷取AccessKey(包括AccessKey ID和AccessKey Secret)。具體操作,請參見擷取AccessKey
  • 已建立資料表並為資料表建立映射關係。具體操作,請分別參見建立資料表建立表的映射關係

步驟一:安裝JDBC驅動

您可以通過以下兩種方式安裝JDBC驅動。

  • 下載Tablestore JDBC驅動並匯入到專案中。具體下載路徑請參見Tablestore JDBC驅動
  • 在Maven專案中加入依賴項
    在Maven工程中使用Tablestore JDBC驅動,只需在pom.xml中加入相應依賴即可。以5.13.5版本為例,在<dependencies>內加入如下內容:
    <dependency>
      <groupId>com.aliyun.openservices</groupId>
      <artifactId>tablestore-jdbc</artifactId>
      <version>5.13.5</version>
    </dependency>                

步驟二:安裝Hibernate

您可以通過以下兩種方式安裝Hibernate。

  • 下載Hibernate安裝包(即hibernate-core-x.x.x.jar)並匯入到專案中。具體下載路徑請參見Hibernate安裝包

    hibernate-core-x.x.x.jar中的x.x.x表示Hibernate的版本號碼,請根據實際下載所需版本的安裝包。

  • 在Maven專案中加入依賴項

    在Maven工程中使用Hibernate,只需在pom.xml中加入相應依賴即可。以3.6.3.Final版本為例,在<dependencies>內加入如下內容:

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.6.3.Final</version>
    </dependency>

步驟三:映射SQL欄位

完成資料庫欄位對應Java Bean建立後,通過映射設定檔將Java Bean的成員變數和資料表欄位一一映射。

  1. 建立資料表欄位對應的Java Bean。
    package hibernate;
    
    public class Trip {
    
        private long tripId;
        private long duration;
        private String startDate;
        private String endDate;
        private long startStationNumber;
        private long endStationNumber;
        private String startStation;
        private String endStation;
        private String bikeNumber;
        private String memberType;
        // ...
    }
  2. 建立映射設定檔,並在映射設定檔中將Java Bean的成員變數和資料表欄位相對應。此處以在hibernate目錄下建立Trip.hbm.xml為例介紹。

    由於目前Tablestore SQL暫時不支援資料插入和更新,因此insert屬性和update屬性均需要設定為false。關於SQL類型支援情況,請參見資料類型映射。關於SQL功能支援情況,請參見SQL支援功能說明

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <!--此處的類名必須與實際類名稱一致。-->
        <class name="hibernate.Trip" table="trips">
            <!-- id元素中配置的欄位為資料表中的主鍵列。-->
            <id name="tripId" column="trip_id" type="long"/>
            <!-- property元素中配置的欄位均為資料表中的屬性列,屬性列必須禁止插入和更新,即insert屬性和update屬性均需要設定為false。-->
            <property name="duration" column="duration" type="long" insert="false" update="false"/>
            <property name="startDate" column="start_date" type="string" insert="false" update="false"/>
            <property name="endDate" column="end_date" type="string" insert="false" update="false"/>
            <property name="startStationNumber" column="start_station_number" type="long" insert="false" update="false"/>
            <property name="endStationNumber" column="end_station_number" type="long" insert="false" update="false"/>
            <property name="startStation" column="start_station" type="string" insert="false" update="false"/>
            <property name="endStation" column="end_station" type="string" insert="false" update="false"/>
            <property name="bikeNumber" column="bike_number" type="string" insert="false" update="false"/>
            <property name="memberType" column="member_type" type="string" insert="false" update="false"/>
        </class>
    </hibernate-mapping>

步驟四:構建SessionFactory

完成Hibernate設定檔設定後,通過載入Hibernate設定檔來建立SessionFactory。

  1. 建立Hibernate設定檔hibernate.cfg.xml後添加如下內容。並根據實際修改對應配置項。
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="hibernate.connection.driver_class">com.alicloud.openservices.tablestore.jdbc.OTSDriver</property>
            <property name="hibernate.connection.url">jdbc:ots:https://myinstance.cn-hangzhou.ots.aliyuncs.com/myinstance</property>
            <property name="hibernate.connection.username">************************</property>
            <property name="hibernate.connection.password">********************************</property>
            <property name="hibernate.connection.autocommit">true</property>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            <!-- 設定為映射設定檔的路徑。-->
            <mapping resource="hibernate/Trip.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
    配置項說明請參見下表。
    配置項 類型 是否必選 樣本 描述
    hibernate.connection.driver_class class com.alicloud.openservices.tablestore.jdbc.OTSDriver Tablestore JDBC驅動的類名,設定為com.alicloud.openservices.tablestore.jdbc.OTSDriver。
    hibernate.connection.url string jdbc:ots:https://myinstance.cn-hangzhou.ots.aliyuncs.com/myinstance 執行個體訪問地址。格式為jdbc:ots:endpoint/instanceName,其中endpoint為執行個體的服務地址。更多資訊,請參見服務地址。instanceName為執行個體名稱,請根據實際修改。

    填寫時必須加上首碼jdbc:ots:

    hibernate.connection.username string ************************ 阿里雲帳號或者RAM使用者的AccessKey ID。
    hibernate.connection.password string ******************************** 阿里雲帳號或者RAM使用者的AccessKey Secret。
    hibernate.connection.autocommit boolean true 是否自動認可。由於Tablestore目前暫不支援事務,因此該配置項必須設定為true。
    hibernate.dialect string org.hibernate.dialect.MySQLDialect Tablestore SQL繼承了MySQL文法,設定為org.hibernate.dialect.MySQLDialect。
  2. 通過載入Hibernate設定檔來構建SessionFactory。
    SessionFactory factory = new Configuration().
      configure("hibernate/hibernate.cfg.xml").
      buildSessionFactory();

步驟五:建立Session查詢資料

Session session = factory.openSession();
Trip trip = (Trip) session.get(Trip.class, 99L); 
System.out.println("trip id: " + trip.getTripId());
System.out.println("start date: " + trip.getStartDate());
System.out.println("end date: " + trip.getEndDate());
System.out.println("duration: " + trip.getDuration());
session.close();
factory.close();

完整樣本

查詢表中主鍵列值為99的行資料,並擷取指定列的值。

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import hibernate.Trip;

public class HibernateDemo {
    public static void main(String[] args) {
        SessionFactory factory = new Configuration().
                configure("hibernate/hibernate.cfg.xml"). // 設定Hibernate設定檔的完整路徑。
                buildSessionFactory();
        Session session = factory.openSession();
        // 設定主索引值為99。如果行資料不存在,則返回null。
        Trip trip = (Trip) session.get(Trip.class, 99L);
        // 列印需要擷取的列值。
        System.out.println("trip id: " + trip.getTripId());
        System.out.println("start date: " + trip.getStartDate());
        System.out.println("end date: " + trip.getEndDate());
        System.out.println("duration: " + trip.getDuration());
        session.close();
        factory.close();
    }
}           

常見問題處理

  • 問題現象:當通過Hibernate使用JDBC驅動查詢資料時出現如下錯誤,我該如何解決?
    Exception in thread "main" org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]
      at org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(EntityTuplizerFactory.java:108)
      at org.hibernate.tuple.entity.EntityTuplizerFactory.constructDefaultTuplizer(EntityTuplizerFactory.java:133)
      at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.<init>(EntityEntityModeToTuplizerMapping.java:80)
      at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:322)
      at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:485)
      at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:133)
      at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:84)
      at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:286)
      .....

    可能原因:缺少javassist-x.x.x.jar包。

    解決方案:安裝javassist-x.x.x.jar包,您可以通過以下兩種方式安裝。
    • 下載javassist安裝包(即javassist-x.x.x.jar)並匯入到專案中。具體下載路徑請參見javassist安裝包

      javassist-x.x.x.jar中的x.x.x表示javassist的版本號碼,請根據實際下載所需版本的安裝包。

    • 在Maven專案中加入依賴項

      在Maven工程中的pom.xml中加入相應依賴即可。此處以3.15.0-GA版本為例,在<dependencies>內加入如下內容:

      <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
      <dependency>
          <groupId>org.javassist</groupId>
          <artifactId>javassist</artifactId>
          <version>3.15.0-GA</version>
      </dependency>
  • 問題現象:當通過Hibernate使用JDBC驅動查詢資料時出現Message: Unknown column '{columnName}' in 'field list'錯誤,我該如何解決?

    可能原因:在SQL映射表中不存在指定列。

    解決方案:確保SQL映射表中存在指定列。您可以通過以下兩種方式實現。
    • 在預定義列中添加指定列,該列會自動同步到SQL映射表中。
    • 通過CREATE TABLE語句建立映射關係時指定該列。具體操作,請參見建立表的映射關係