【问题标题】:Selecting through multiple mapped tables with HQL?使用 HQL 通过多个映射表进行选择?
【发布时间】:2021-09-14 13:06:36
【问题描述】:

我很难使用 HQL 从给定的 Country 中选择 Brand。 我做了一些逆向工程,所以你可以想象我的数据库是如何建模的:

To select the Brand from the right Country I'd have to go through Address as well as their City and State.

就带注释的映射而言,我已经这样做了:

品牌

@Table(name = "brand")
public class Brand extends BasicModel {

    private String name;
    @OneToMany(targetEntity = Address.class, cascade = CascadeType.ALL,
                fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinTable(name="brand_address",
            joinColumns = { @JoinColumn(name = "brand_id") },
            inverseJoinColumns = { @JoinColumn(name = "address_id") })
    private Set<Address> address;

地址

@Table(name = "address")
public class Address extends BasicModel {

    @NotNull
    @ManyToOne
    private AddressCity city;

AddressCity 被映射到 AddressStateAddressCountry 被映射到 AddressCity 被上面的Address 映射的方式相同。

brand_address是由Hibernate自动创建的。

现在使用 SQL 我需要加入所有这些表才能到达 Country 但是,因为它已使用 Hibernate 注释进行映射,我应该如何编写HQL 从给定的Country 中选择Brand

信息:当我创建一个包含一组地址的国家/地区时,表 brand_address 被正确填充。

到目前为止的工作只是选择Brand,Hibernate 将返回所有填充的对象。我可以这样做:

    Query query = session
            .createQuery("from Brand brand " +
                            "where brand.name = :brandName " +
                                "and brand.deleted is null");
    query.setParameter("brandName", brandName);

有了这个,我可以轻松地过滤掉具有该名称的 Brands,但从其他 Countries 中过滤掉,但这听起来不像是最佳做法......

到目前为止没有什么效果当我尝试时:

    Query query = session
            .createQuery("from Brand brand " +
                            "where brand.name = :brandName " +
                                "and Address.city.state.country.code = :countryCode " +
                                "and brand.deleted is null");
    query.setParameter("brandName", brandName);
    query.setParameter("countryCode", countryCode);

    Query query = session
            .createQuery("from Brand brand " +
                            "where brand.name = :brandName " +
                                "and AddressCountry.code = :countryCode " +
                                "and brand.deleted is null");
    query.setParameter("brandName", brandName);
    query.setParameter("countryCode", countryCode);

我应该如何解决? 有没有办法让我不用在上述查询中编写多个连接就可以到达country? 我是否应该使用它已经工作的方式全部选择它并在我的 DAO 中过滤结果?

我一直在互联网上搜索此内容,但只找到了有关如何映射和插入信息的信息,而不是真正有关如何编写将通过表进行选择的查询的信息。

我提前感谢你们美丽的人可以通过我的方式发送的任何帮助和建议!

更新 1:我已经尝试添加

left join brand.address as a
with a.city.state.country.code = :countryCode

这导致了一个新的错误:

java.sql.SQLSyntaxErrorException:“on 子句”中的未知列“addresscit3_.state_id”

使用以下日志:

14:02:43.646 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [brand brand0_]
14:02:43.646 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [inner join address_state addresssta4_ on addresscit3_.state_id=addresssta4_.id]
14:02:43.646 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [inner join address_country addresscou5_ on addresssta4_.country_id=addresscou5_.id]
14:02:43.647 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [inner join brand_address addresses1_ on brand0_.id=addresses1_.brand_id inner join address address2_ on addresses1_.address_id=address2_.id and (addresscou5_.code=?)]
14:02:43.647 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [inner join address_city addresscit3_ on address2_.city_id=addresscit3_.id]
14:02:43.647 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker - select >> end [level=1, statement=select]

更新 2:解决方案

使用@guillaume 建议的with 键确实改变了错误,使得连接顺序似乎放错了位置......我的一个朋友建议使用join fetch,因为延迟加载,我调整了查询直到一切就绪,如下所示:

    .createQuery("from Brand brand " +
                    "join fetch brand.addresses as a " +
                        "where brand.name = :brandName " +
                        "and a.city.state.country.code = :countryCode " +
                        "and brand.deleted is null");

【问题讨论】:

    标签: java mysql sql hibernate hql


    【解决方案1】:

    您不需要“加入获取”您的品牌实体,您的查询也应该与“加入”一起使用。

    查看What is the difference between JOIN and JOIN FETCH when using JPA and Hibernate

    【讨论】:

    • 我尝试了多种不同的方式,没有fetch 它将无法工作......也许我在其他地方还缺少一些东西。由于到目前为止它一直在工作,我将保持原样。感谢您的链接:)
    【解决方案2】:

    条件Address.city.state.country.code = :countryCode 没有意义,因为 Address 实际上是地址的Set(命名为地址可能更清楚)。

    试试这个:

    from Brand brand
    left join brand.address as a
    with a.city.state.country.code = :countryCode
    

    【讨论】:

    • 我试过这个并用结果更新了问题......我想我现在更接近了,谢谢!
    • 你映射AddressCity实体的表显然没有state_id列,我认为你需要检查你的数据库结构
    • 我刚刚修复它并发布到问题的末尾,感谢您添加加入并将 Set name 更改为地址的想法!我不得不使用 fetch 而不是 with,将国家代码添加到 where 子句中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多