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 的二级缓存是否适合于此?如果适合,我该如何配置它?
- 如果没有,是否还有其他 Hibernate 功能可以在这里使用?
目前大约有 100,000 个节点,因此我不愿意采用查询每个节点并将其缓存在应用程序中某处的强力方法,因为这不会扩展到更多数量的节点,而且看起来像它会在应用程序和 Hibernate 内部( session 、二级缓存等)之间复制数据。
最佳答案
我不是 100% 清楚你想在这里做什么... Configuration.addNode()
(或你没有展示的其他方法)是否涉及一些业务逻辑?
如果没有,您最好运行多个批量更新查询来将节点与配置关联起来。
如果确实如此(意味着您必须加载并检查每个节点),您可以:
- 将整个
lotsOfNames
列表分成多个批处理,例如 1000 个名称(您可以使用这个数字来查看什么可以提供最佳性能)。 - 通过使用
name IN(?)
条件的查询一次性加载整批节点。 - 将它们添加到您的配置中。
- 刷新 session (并且可以选择提交/启动新事务)。
应该会快很多,因为您将执行 1 个查询而不是 1000 个查询,并将插入批量处理在一起。
关于java - Hibernate:如何急切地获取未关联的实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1467410/