Hibernate HQL 多对一连接

Posted

技术标签:

【中文标题】Hibernate HQL 多对一连接【英文标题】:Hibernate HQL many to one join 【发布时间】:2016-11-28 17:38:10 【问题描述】:

我在 mysql 中有 2 个表,blocked_historiesblocked_detail_histories。 block_detail_histories 表与 block_histories 具有多对一的休眠关系。表创建脚本如下所示

blocked_history

CREATE TABLE `blocked_histories` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `type` VARCHAR(32) NOT NULL,
  `no_ecash` varchar(13) NOT NULL,
  `cif` VARCHAR(32) DEFAULT NULL,
  `reason_id` INT(4) NOT NULL,
  `desc` TEXT,
  `status` VARCHAR(32) NOT NULL,
  `created_date` DATETIME NOT NULL,
  `created_by` VARCHAR(100) NOT NULL,
  `total_balance` DECIMAL(15,6) NOT NULL,
  `broker` int(11) NOT NULL,
  `blocked_id` INT(11) NOT NULL UNIQUE,
  `remark` text,
  PRIMARY KEY (`id`),
    CONSTRAINT `CUSTOMFIELD_ID_FK` FOREIGN KEY (`reason_id`) REFERENCES `custom_field_possible_values` (`id`)
)  ENGINE=INNODB AUTO_INCREMENT=312 DEFAULT CHARSET=latin1;

blocked_detail_histories

CREATE TABLE `blocked_detail_histories` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `blocked_id` INT(11) NOT NULL,
  `no_ecash` VARCHAR(13) DEFAULT NULL,
  `prev_group` INT(11) NOT NULL,
  `balance` DECIMAL(15,6) NOT NULL,
  PRIMARY KEY (`id`),
   KEY `BLOCKED_ID_FK` (`blocked_id`),
   CONSTRAINT `BLOCKED_ID_HISTORIES_FK` FOREIGN KEY (`blocked_id`) REFERENCES `blocked_histories` (`blocked_id`)
)  ENGINE=INNODB AUTO_INCREMENT=312 DEFAULT CHARSET=latin1;

hibernate 映射看起来像这样

blocked_history

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class dynamic-insert="true" dynamic-update="true"
        name="nl.strohalm.cyclos.entities.groups.BlockedHistories"
        table="blocked_histories">
        <id name="id" type="long">
            <column name="id" sql-type="bigint" />
            <generator class="native" />
        </id>
        <property name="type" column="type" type="string" not-null="true" length="32" />
        <property name="noEcash" column="no_ecash" type="string" not-null="true" length="13" />
        <property name="cif" column="cif" type="string" length="32" />

        <!--  <property name="reasonId" column="reason_id" type="int" not-null="true" length="11" /> -->
        <many-to-one name="reasonId" class="nl.strohalm.cyclos.entities.customization.fields.CustomFieldPossibleValue">
            <column name="reason_id" sql-type="integer"></column>
        </many-to-one>

        <property name="desc" column="desc" type="text" not-null="true" />
        <property name="status" column="status" type="string" length="32" />
        <property name="createdDate" column="created_date" type="calendar" not-null="true" />
        <property name="createdBy" column="created_by" type="string" not-null="true" length="100"/>
        <property name="totalBalance" column="total_balance" type="big_decimal" not-null="true" precision="15" scale="6" />
        <property name="brokerId" column="broker" type="int" not-null="true" length="11" />
        <property name="remark" column="remark" type="text" />
        <property name="blockedId" column="blocked_id" type="int" not-null="true" length="11" />
    </class>

</hibernate-mapping>

blocked_detail_histories

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class dynamic-insert="true" dynamic-update="true"
        name="nl.strohalm.cyclos.entities.groups.BlockedDetailHistories"
        table="blocked_detail_histories">
        <id name="id" type="long">
            <column name="id" sql-type="bigint" />
            <generator class="native" />
        </id>
        <many-to-one name="blockedHistories" class="nl.strohalm.cyclos.entities.groups.BlockedHistories">
            <column name="blocked_id" sql-type="integer"></column>
        </many-to-one>
        <property name="noEcash" column="no_ecash" type="string" not-null="true" length="13" />
        <property name="prevGroup" column="prev_group" type="int" not-null="true" length="11" />
        <property name="balance" column="balance" type="big_decimal" not-null="true" precision="15" scale="6" />
    </class>

</hibernate-mapping>

如您所见,blocked_detail 历史表与blocked_histories 表具有多对一关系(在“blockedHistories”列中)

我尝试运行一个简单的 mysql 查询来连接两个看起来像这样的表

select bh.created_date, bdh.no_ecash, bh.type,
    bh.cif, bh.desc, bh.reason_id,
    bh.status, bh.created_by, bh.remark
from blocked_detail_histories bdh
join blocked_histories bh 
where bdh.blocked_id=4;

上面的 mysql 查询工作正常,但是当我尝试将上面的 mysql 查询转换为 HQL 查询时,结果什么也没给我。HQL 看起来像这样(这里的“:id”是 java NamedParameters)

select bdh.blockedHistories.blockedId
from BlockedDetailHistories bdh"
join bdh.blockedHistories bh
where bh.blockedId = :id

我试过这个,但什么也没给我

select bh.createdDate, bdh.noEcash, bh.type,
bh.cif, bh.desc, bh.reasonId,
bh.status, bh.createdBy, bh.remark
from BlockedDetailHistories bdh
join bdh.blockedHistories bh
where bh.blockedId = :id

任何建议我在这里缺少什么?关系定义可能吗?还是别的什么?任何帮助将不胜感激:)

【问题讨论】:

SQL 查询对于联接似乎不正确。您应该使用“ON”子句而不是“where” 示例:SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate FROM Orders INNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID; 来源:w3schools.com/sql/sql_join.asp 【参考方案1】:

不是 xml hibernate 映射方面的专家, 但是您是否为休眠实体类应用了获取类型, 如果你定义了这样,那么你可以重试上面的查询,如下所示(在惰性获取类型的情况下)

select bdh.blockedHistories.blockedId
from BlockedDetailHistories bdh
left join fetch bdh.blockedHistories bh
where bh.blockedId = :id

【讨论】:

以上是关于Hibernate HQL 多对一连接的主要内容,如果未能解决你的问题,请参考以下文章

hibernate中session,HQL,持久化,一对多,多对一

Hibernate 双向 多对一

Hibernate,关系映射的多对一单向关联多对一双向关联一对一主键关联一对一外键关联多对多关系关联

hibernate - 在多对一约束上不受支持的 SQL 类型 2005

hibernate学习四 hibernate关联关系映射

Hibernate单向“多对一”关联