1

Java Persistence with Hibernate 展示了许多如何急切获取关联实体的示例,例如:

  • 将@org.hibernate.annotations.BatchSize 添加到关联的类
  • 将@org.hibernate.annotations.Fetch 添加到引用关联类的字段中
  • 在 HQL 查询等中使用“fetch”关键字...

但是,在我的情况下,我正在处理一个运行缓慢的过程,该过程负责建立与感兴趣的实体类的关联。这意味着 - 在执行时 - 我不能查询一个实体并要求它急切地获取另一个实体的所有关联实例,因为不存在这样的关联。

换句话说,这个过程看起来像这样:

public class InitConfig {

    private final SessionFactory sessionFactory;
    private final NodeManager nodeManager;

    public void run() {

        final Configuration config = new Configuration("NewConfiguration", new HashSet<Node> ());
        for(String name : lotsOfNames) {

            //Lots of these queries run slowly
            final Node node = this.nodeManager.getNode(name);
            config.addNode(node);
        }
        this.sessionFactory.getCurrentSession().save(config);
    }
}

相关的 DAO (NodeManager) 和慢查询实体 (Node) 如下所示:

public class NodeManager {

    private final SessionFactory sessionFactory;

    public Node getNode(String name) {

        final Session db = this.sessionFactory.getCurrentSession();
        final Query query = db.createQuery("from NODE where NAME = :name");
        query.setString("name", name);
        return (Node)query.uniqueResult();
    }
}

@Entity(name="NODE")
public class Node {

    @GeneratedValue(strategy=GenerationType.TABLE)
    @Id @Column(name="ID")
    private Long id;

    private @Column(name="NAME", nullable=false, unique=true) String name;

    //Other properties and associations...
}

最后,由缓慢运行的进程创建的实体:

@Entity(name="CONFIGURATION")
public class Configuration {

    @Id @GeneratedValue @Column(name="ID")
    private Long id;
    private @Column(name="NAME", nullable=false, unique=true) String name;

    @ManyToMany
    @JoinTable(
        name="CONFIGURATION_NODE",
        joinColumns=@JoinColumn(name="CONFIGURATION_ID", nullable=false),
        inverseJoinColumns=@JoinColumn(name="NODE_ID", nullable=false))
    private Set<Node> nodes = new HashSet<Node> ();

    public void addNode(Node node) {

        this.nodes.add(node);
    }
}

我的问题是:如何修改 Hibernate 配置和/或代码以一次急切地获取多个 Node 实例?

后续问题将是:

  • Hibernate 的 2 级缓存是否适合于此,如果适合 - 我该如何配置它?
  • 如果没有,这里是否可以使用其他一些 Hibernate 功能?

目前大约有 100,000 个节点,所以我不愿意采取蛮力的方法来查询每个节点并将其缓存在应用程序的某个地方,因为这不会扩展到更多的节点并且看起来会重复应用程序和 Hibernate 内部(会话、二级缓存等)之间的数据。

4

1 回答 1

2

我不是 100% 清楚你在这里试图做什么...... Configuration.addNode()(或你没有展示的其他方法)是否涉及一些业务逻辑?

如果没有,您可能会更好地运行多个批量更新查询以将您的节点与配置相关联。

如果是这样(意味着您必须加载并检查每个节点),您可以:

  1. 将你的整个lotsOfNames列表分成一批,比如 1000 个名字(你可以用这个数字来看看什么能提供最佳性能)。
  2. name IN(?)通过带有条件的查询一次加载整批节点。
  3. 将它们添加到您的配置中。
  4. 刷新会话(以及,可选地,提交/启动新事务)。

应该快得多,因为您将执行 1 个查询而不是 1000 个查询并将您的插入批处理。

于 2009-09-23T17:29:00.093 回答