在Hibernate的load()方法的上下文中,代理是什么?

2022-09-01 07:12:33

load() 方法的 Hibernate 文档说:

请注意,如果没有匹配的数据库行,load() 将引发不可恢复的异常。如果类是使用代理映射的,则 load() 只返回一个未初始化的代理,并且在调用代理的方法之前实际上不会命中数据库。如果您希望创建与对象的关联而不实际从数据库中加载该对象,这将非常有用。如果为类映射定义了批大小,它还允许将多个实例作为批处理加载。

请通过以粗体解释上面突出显示的部分的含义来帮助我理解这一点。


答案 1

代理是由Hibernate动态生成的类,用于帮助延迟加载。例如,如果你有一个类,Hibernate将生成一个扩展的代理类。CatCat

如果您获得此代理的未初始化实例,则基本上其所有字段都将为 null,但 ID 除外,因为 Hibernate 尚未命中数据库。现在,当您第一次在此代理上调用方法时,它将意识到它未初始化,并且它将查询数据库以加载其属性。这是可能的,因为动态生成的类将重写基类的方法并添加此初始化/未初始化的检查。

现在假设您的类不是代理并且具有关联,当您加载 Cat 对象时,Hibernate 将需要加载它的所有属性。因此,如果您加载一个对象,Hibernate还需要加载其父亲和父亲的父亲等。使用代理使 Hibernate 能够仅加载所需的实例。CatfatherCat

Cat cat1 = (Cat) session.load(1);
Cat cat2 = (Cat) session.load(2);
Cat cat3 = (Cat) session.load(3);

cat1.meow(); // this will cause Hibernate to run a query to load cat1's data
cat2.meow(); // this will cause Hibernate to run a query to load cat2's data

// After this cat3 is still an uninitiated proxy because it has not been used

batch-size是Hibernate的另一个功能,在大多数情况下,它有助于处理延迟加载。基本上,这个想法是Hibernate跟踪未初始化的代理,当需要初始化其中一个时,将执行单个查询以加载到代理(而不仅仅是一个代理/查询)。batch-size

Cat cat1 = (Cat) session.load(1);
Cat cat2 = (Cat) session.load(2);

cat1.meow(); // if batch-size >= 2, cat1 and cat2 will be loaded in a single query
cat2.meow(); // no query will be executed here

答案 2

这类似于延迟加载关联,但可能被视为更多的“延迟创建”。

代理是在运行时实现的子类。Hibernate 创建一个代理(正在获取的类的子类),而不是直接查询数据库,并且每当调用其方法之一时,此代理将从数据库中加载“real”对象。

第二个突出显示的文本解释说,如果调用多个实例,则可以将它们作为批处理提取,从而减少到数据库的往返。load()

这也是 load() 和 get() 之间的区别,加载是延迟加载对象,而 get 则立即从数据库获取对象


推荐