gpt4 book ai didi

java - 获取集合子集的策略

转载 作者:搜寻专家 更新时间:2023-11-01 02:54:39 25 4
gpt4 key购买 nike

我有一个场景,我的应用程序可以在有限的时间窗口内访问 session ,在此期间它必须从数据库中获取数据到内存中,然后只使用内存中的数据来处理请求。

数据模型是一个简单的一对多关联,例如:

<class name="com.foo.Road" table="road">
<id name="oid" column="oid"/>

<map name="carCountMap" fetch="subselect">
<key column="road_oid" foreign-key="oid"/>
<index column="time_oid" type="long" />
<one-to-many class="com.foo.CarCount" />
</map>

<map name="truckCountMap" fetch="subselect">
<key column="road_oid" foreign-key="oid"/>
<index column="time_oid" type="long" />
<one-to-many class="com.foo.TruckCount" />
</map>
</class>

现在假设汽车和卡车计数数据存在了几年,这远远超出了内存所能容纳的范围。此外,我只对加载过去 3 个月的汽车数量感兴趣。

我的问题是,使用 hibernate 加载此数据的最佳方式是什么:

  • road.getCarCountMap() 返回最近3个月的汽车数量集合(可能为空)
  • 我不会得到一些需要很长时间才能处理的疯狂笛卡尔积
  • 没有LazyInitializationException s 在我关闭 session 后被抛出

我尝试过的一些事情是:

1.制作carCountMap渴望收集并指定一个 where映射上的属性,例如:

<map name="carCountMap" fetch="subselect" lazy="false" where="time_oid > 1000">(类似于 truckCountMap )

这最符合我想要的集合语义,但不幸的是,它迫使我硬编码一个值,所以我不能真正引用过去 3 个月。 time_oid每天增加 1。

2. 将 map 定义为惰性 map 并使用 hql 查询手动连接 3 个表:

    from Road r
left outer join fetch r.carCountMap ccm
left outer join fetch r.truckCoutnMap tcm
where (ccm.time.oid > :startDate)
or (tcm.time.oid > :startDate)

问题是生成的查询返回数百万行,而它应该是 10k 条道路 * 每月(每周)4 次测量 * 3 个月 = ~120k。此查询在大约一个小时内完成,这很荒谬,因为方法 #1(就我而言加载完全相同的数据)在 3 分钟内完成。

3. 将 map 定义为惰性 map 并首先使用条件加载道路,然后运行其他查询以填充集合

    List roadList = session.createCriteria(Road.class).list();

session.getNamedQuery("fetchCcm").setLong("startDate", startDate).list();
session.getNamedQuery("fetchTcm").setLong("startDate", startDate).list();

return roadList;

这会触发正确的查询,但检索到的汽车和卡车数量不会附加到 Road roadList 中的对象.因此,当我尝试访问任何 Road 对象的计数时,我得到一个 LazyInitializationException .

4. 将 map 定义为惰性 map ,使用criteria.list()要加载所有道路,请遍历过去 3 个月内的所有测量日期,以便强制加载这些值。

我还没有试过这个,因为它听起来真的很笨拙,而且我不相信它会摆脱 LazyInitializationException

  • 对于我在使用这些方法时遇到的问题,是否有任何解决方法?
  • 是否有更好的方法?

最佳答案

在进一步挖掘之后,它看起来像 hibernate filters正是我为此需要的解决方案。

它们基本上提供了一个构造,在集合或类上具有 where 属性,并在运行时绑定(bind)参数。

在映射文件中,定义过滤器并将其附加到集合:

<class name="com.foo.Road" table="road">
<id name="oid" column="oid"/>

<map name="carCountMap" fetch="subselect">
<key column="road_oid" foreign-key="oid"/>
<index column="time_oid" type="long" />
<one-to-many class="com.foo.CarCount" />
<filter name="byStartDate" condition="time_oid > :startDate" />
</map>

<map name="truckCountMap" fetch="subselect">
<key column="road_oid" foreign-key="oid"/>
<index column="time_oid" type="long" />
<one-to-many class="com.foo.TruckCount" />
<filter name="byStartDate" condition="time_oid > :startDate" />
</map>
</class>

<filter-def name="byStartDate">
<filter-param name="startDate" type="long"/>
</filter-def>

然后在dao中,启用过滤器,绑定(bind)参数并运行查询:

session.enableFilter("byStartDate").setParameter("startDate", calculatedStartDateOid);
return session.createCriteria(Road.class).list();

关于java - 获取集合子集的策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4054683/

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