通过Hibernate使用SQL查询数据

Hibernate是面向Java环境的对象/关系映射(ORM)解决方案,您可以通过Hibernate使用表格存储的JDBC驱动来快速访问表格存储。

背景信息

Hibernate是面向Java环境的对象/关系映射(ORM)解决方案,主要负责从Java类到数据库表的映射以及从Java数据类型到SQL数据类型的映射,同时还支持数据查询。使用Hibernate能有效减少在SQLJDBC中手动处理数据所花费的时间。更多信息,请参见Hibernate官网文档

注意事项

目前支持使用SQL查询功能的地域有华东1(杭州)、华东2(上海)、华北2(北京)、华北3(张家口)、华北5(呼和浩特)、华北6(乌兰察布)、华南1(深圳)、西南1(成都)、中国香港、新加坡、印度尼西亚(雅加达)、德国(法兰克福)和美国(弗吉尼亚)。

前提条件

  • 如果要使用RAM用户进行操作,请确保已创建RAM用户,并为RAM用户授予所有SQL操作权限,即在自定义权限策略中配置"Action": "ots:SQL*"。具体操作,请参见通过RAM PolicyRAM用户授权

  • 已获取AccessKey(包括AccessKey IDAccessKey Secret)。具体操作,请参见创建AccessKey

  • 已创建数据表并为数据表创建映射关系。具体操作,请分别参见创建数据表创建表的映射关系

使用流程

步骤一:安装JDBC驱动

您可以通过以下两种方式安装JDBC驱动。

  • 下载表格存储JDBC驱动并导入到项目中。具体下载路径请参见表格存储JDBC驱动

  • Maven项目中加入依赖项

    Maven工程中使用表格存储JDBC驱动,只需在pom.xml中加入相应依赖即可。以5.17.0版本为例,在<dependencies>内加入如下内容:

    <dependency>
      <groupId>com.aliyun.openservices</groupId>
      <artifactId>tablestore-jdbc</artifactId>
      <version>5.17.0</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;
        
        // 添加设置/返回字段值方法。
        // 此处以tripId字段为例,其他字段类似,请根据实际需要添加。
        public void setTripId(Long tripId){
            this.tripId =tripId
        }
        public Long getTripId() {
            return tripId;
        }
    }
  2. 创建映射配置文件,并在映射配置文件中将Java Bean的成员变量和数据表字段相对应。此处以在hibernate目录下创建Trip.hbm.xml为例介绍。

    重要

    由于目前表格存储SQL暂时不支持数据插入和更新,因此insert属性和update属性均需要设置为false。关于SQL类型支持情况,请参见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

    表格存储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

    是否自动提交。

    重要

    由于表格存储目前暂不支持事务,因此autocommit配置项必须设置为true。

    hibernate.dialect

    string

    org.hibernate.dialect.MySQLDialect

    表格存储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驱动查询数据时出现如下错误,我该如何解决?

  • 问题现象

    当通过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'错误,我该如何解决?

  • 问题现象

    当通过Hibernate使用JDBC驱动查询数据时出现Message: Unknown column '{columnName}' in 'field list'错误。

  • 可能原因

    SQL映射表中不存在指定列。

  • 解决方案

    确保SQL映射表中存在指定列。您可以通过以下两种方式实现。

    • 在预定义列中添加指定列,该列会自动同步到SQL映射表中。

    • 通过CREATE TABLE语句创建映射关系时指定该列。具体操作,请参见创建表的映射关系

    • 通过ALTER TABLE语句为已存在的映射表添加或删除属性列。具体操作,请参见更新映射表属性列

相关文档