gpt4 book ai didi

hibernate - 查询 hasMany 关系的属性

转载 作者:行者123 更新时间:2023-12-03 06:52:48 24 4
gpt4 key购买 nike

我在我正在处理的域中有以下关联(不幸的是实际上不是盗版)。一艘船有很多海盗。我希望能够找到所有有船长且船员中没有旱鸭子的船只。

class Pirate {

String name
Rank rank

enum Rank {
CAPTAIN,
DECK_HAND,
LAND_LUBBER
}

}

class Ship {

static hasmany = [crew:Pirate]

}

我正在尝试使用 Hibernate 标准,因为从长远来看,我希望这是一个可以与其他查询链接的命名查询。这是我正在使用的标准。

def pirateShips = Ship.withCriteria {
crew {
eq('rank', Pirate.Rank.CAPTAIN)
not {
eq('rank', Pirate.Rank.LAND_LUBBER)
}
}
}

当我创建以下实体时,我没有得到预期的结果。

def blackbeard = new Pirate(name:'Blackbeard', rank:Pirate.Rank.CAPTAIN).save()
def deckHand = new Pirate(name:'Deck Hand', rank:Pirate.Rank.DECK_HAND).save()
def landLubber = new Pirate(name:'Land Lubber', rank:Pirate.Rank.LAND_LUBBER).save()

def ship = new Ship(name:'Ship 1', crew:[blackbeard]).save()
def infiltrator = new Ship(name:'Ship 2', crew:[blackbeard, landLubber]).save()
def normalShip = new Ship(name:'Ship 3', crew:[blackbeard, deckHand]).save(flush:true)

运行上述查询会导致所有 3 艘船都被返回,而我本希望只返回 1 号船和 3 号船(2 号船有一艘讨厌的陆地船,对我来说没有用)。

有没有办法使用标准 API 来生成这样的查询?如果不是,我该如何在 HQL 中编写查询?

最佳答案

您的查询不起作用的原因主要是由于 SQL 连接的性质。如果任何单独的行符合您的条件,它将返回一艘船。连接中有些行是船长,但不是陆上人(即每个黑 mustache 行),因此您将收回所有船只。这样写,标准并不是考虑所有机组成员,而是考虑每个机组成员。

有几种不同的方法可以解决这个问题。一种是使用子选择查询。也许可以将其写在标准中,但我对它们并不熟悉,因为我更喜欢 HQL,因为它看起来更像 SQL,我对此很满意。

下面是返回预期船舶 1 和 3 的 HQL 查询示例:

def blackbeard = Pirate.buildLazy(name: 'Blackbeard', rank: Pirate.Rank.CAPTAIN)
def deckHand = Pirate.buildLazy(name: 'Deck Hand', rank: Pirate.Rank.DECK_HAND)
def landLubber = Pirate.buildLazy(name: 'Land Lubber', rank: Pirate.Rank.LAND_LUBBER)

def ship = Ship.buildLazy(name: 'Ship 1').with { crew = [blackbeard] }
def infiltrator = Ship.buildLazy(name: 'Ship 2').with { crew = [blackbeard, landLubber] }
def normalShip = Ship.buildLazy(name: 'Ship 3').with { crew = [blackbeard, deckHand] }

def pirateShips = Ship.executeQuery( """
select s from Ship s
join s.crew as p
where p.rank = :captain
and s not in
(select s1 from Ship s1
join s1.crew as p1
where p1.rank = :landLubber)
""",
[captain: Pirate.Rank.CAPTAIN, landLubber: Pirate.Rank.LAND_LUBBER] )
assert( ["Ship 1", "Ship 3"] == pirateShips.name.sort() )

(我还使用 build-test-data 插件来延迟构建实例,而不是更新它们,因为它使脚本更容易多次运行,而无需一直重新启动 grails 控制台)。

在这个查询中,我找到了所有有船长的船只,并从该集合中删除了所有有陆地滑手的船只。

关于hibernate - 查询 hasMany 关系的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3142897/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com