gpt4 book ai didi

java - 如何使用旧的 hibernate 条件进行批处理?

转载 作者:行者123 更新时间:2023-12-01 09:40:33 24 4
gpt4 key购买 nike

我仍在使用旧的org.hibernate.Criteria,并且越来越对获取模式感到困惑。在各种查询中,我需要以下所有变体,因此无法通过注释进行控制。我只是将所有内容都切换为@ManyToOne(fetch=FetchType.LAZY),否则,就不会更改查询中的任何内容。
到目前为止,我所能找到的要么涉及HQL或JPA2,要么仅提供两种选择,但我需要它作为旧标准以及(至少)以下三种情况:

  • 进行JOIN,然后从两个表中获取。除非数据过于冗余(例如,主数据很大或结果重复多次),否则就可以了。在SQL中,我会写SELECT * FROM item JOIN order on item.order_id = order.idWHERE ...;
  • 执行JOIN,从第一个表中获取,并从另一个表中分离。这通常是先前查询的更有效的变体。在SQL中,我会写SELECT item.* FROM item JOIN order on item.order_id = order.idWHERE ...; SELECT order.* FROM order WHERE ...;
  • 执行JOIN,但不要获取联接的表。例如,这对于基于其他表的数据进行排序很有用。在SQL中,我会写SELECT item.* FROM item JOIN order on item.order_id = order.idWHERE ...ORDER BY order.name, item.name;

  • 看起来好像没有显式指定 fetch=FetchType.LAZY,就像第一种情况一样,所有内容都急切地获取,这有时太糟糕了。我猜想,使用 Criteria#setFetchMode,我可以得到第三种情况。我还没有尝试过,因为我仍然想念第二种情况。我知道这是有可能的,因为有 @BatchSize批注。
  • 我对以上内容正确吗?
  • 是否有办法以旧标准获取第二种情况?

  • 更新
    似乎使用 createAlias()会导致急切地获取所有内容。有一些重载允许指定 JoinType,但是我需要指定访存类型。现在,我感到更加困惑。

    最佳答案

    是的,您可以使用FetchType.LAZY,BatchSize,不同的访存模式和projections来满足这三种情况(请注意,我刚刚用Restrictions.like("name", "%s%")组成了“where”子句,以确保检索到许多行):

  • 进行JOIN,然后从两个表中获取。
    因为项目的顺序是FetchType.LAZY,即the default fetch mode will be 'SELECT',所以只需将其设置为“JOIN”即可从联接而不是单独的查询中获取相关实体数据:
    Session session = entityManager.unwrap(org.hibernate.Session.class);
    Criteria cr = session.createCriteria(Item.class);
    cr.add(Restrictions.like("name", "%s%"));
    cr.setFetchMode("order", FetchMode.JOIN);
    List results = cr.list();
    results.forEach(r -> System.out.println(((Item)r).getOrder().getName()));
    产生的单个SQL查询:
    select
    this_.id as id1_0_1_,
    this_.name as name2_0_1_,
    this_.order_id as order_id3_0_1_,
    order2_.id as id1_1_0_,
    order2_.name as name2_1_0_
    from
    item_table this_
    left outer join
    order_table order2_
    on this_.order_id=order2_.id
    where
    this_.name like ?
  • 进行JOIN,从第一个表中获取,并从另一个表中获取。
    将获取模式保留为默认的“SELECT”,为在排序中使用其列的顺序创建别名,并使用projection选择所需的列子集,包括外键:
    Session session = entityManager.unwrap(org.hibernate.Session.class);
    Criteria cr = session.createCriteria(Item.class);
    cr.add(Restrictions.like("name", "%s%"));
    cr.createAlias("order", "o");
    cr.addOrder(org.hibernate.criterion.Order.asc("o.id"));
    cr.setProjection(Projections.projectionList()
    .add(Projections.property("id"), "id")
    .add(Projections.property("name"), "name")
    .add(Projections.property("order"), "order"))
    .setResultTransformer(org.hibernate.transform.Transformers.aliasToBean(Item.class));
    List results = cr.list();
    results.forEach(r -> System.out.println(((Item)r).getOrder().getName()));

    产生的第一个SQL查询:
    select
    this_.id as y0_,
    this_.name as y1_,
    this_.order_id as y2_
    from
    item_table this_
    inner join
    order_table o1_
    on this_.order_id=o1_.id
    where
    this_.name like ?
    order by
    o1_.id asc
    及后续批次(请注意,我在Order类上使用了@BatchSize(value=5)):
    select
    order0_.id as id1_1_0_,
    order0_.name as name2_1_0_
    from
    order_table order0_
    where
    order0_.id in (
    ?, ?, ?, ?, ?
    )
  • 进行JOIN,但不要获取联接的表。
    与前面的情况相同,但是不执行任何操作来提示加载延迟加载的订单:
    Session session = entityManager.unwrap(org.hibernate.Session.class);
    Criteria cr = session.createCriteria(Item.class);
    cr.add(Restrictions.like("name", "%s%"));
    cr.createAlias("order", "o");
    cr.addOrder(Order.asc("o.id"));
    cr.setProjection(Projections.projectionList()
    .add(Projections.property("id"), "id")
    .add(Projections.property("name"), "name")
    .add(Projections.property("order"), "order"))
    .setResultTransformer(org.hibernate.transform.Transformers.aliasToBean(Item.class));
    List results = cr.list();
    results.forEach(r -> System.out.println(((Item)r).getName()));
    产生的单个SQL查询:
    select
    this_.id as y0_,
    this_.name as y1_,
    this_.order_id as y2_
    from
    item_table this_
    inner join
    order_table o1_
    on this_.order_id=o1_.id
    where
    this_.name like ?
    order by
    o1_.id asc

  • 我在所有情况下的实体均保持不变:
    @Entity
    @Table(name = "item_table")
    public class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    private Order order;

    // getters and setters omitted
    }

    @Entity
    @Table(name = "order_table")
    @BatchSize(size = 5)
    public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // getters and setters omitted
    }

    关于java - 如何使用旧的 hibernate 条件进行批处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61992910/

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