10.3. 装载对象

优质
小牛编辑
131浏览
2023-12-01

如果你知道某个实例的持久化标识(identifier),你就可以使用 Sessionload() 方法来获取它。load() 的另一个参数是指定类的对象。本方法会创建指定类的持久化实例,并从数据库加载其数据(state)。

Cat fritz = (Cat) sess.load(Cat.class, generatedId);
// you need to wrap primitive identifiers
long id = 1234;
DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id) );

此外,你可以把数据(state)加载到指定的对象实例上(覆盖掉该实例原来的数据)。

Cat cat = new DomesticCat();
// load pk's state into cat
sess.load( cat, new Long(pkId) );
Set kittens = cat.getKittens();

请注意如果没有匹配的数据库记录,load() 方法可能抛出无法恢复的异常(unrecoverable exception)。如果类的映射使用了代理(proxy),load() 方法会返回一个未初始化的代理,直到你调用该代理的某方法时才会去访问数据库。 若你希望在某对象中创建一个指向另一个对象的关联,又不想在从数据库中装载该对象时同时装载相关联的那个对象,那么这种操作方式就用得上的了。如果为相应类映射关系设置了 batch-size,那么使用这种操作方式允许多个对象被一批装载(因为返回的是代理,无需从数据库中抓取所有对象的数据)。

如果你不确定是否有匹配的行存在,应该使用 get() 方法,它会立刻访问数据库,如果没有对应的记录,会返回 null。

Cat cat = (Cat) sess.get(Cat.class, id);
if (cat==null) {
    cat = new Cat();
    sess.save(cat, id);
}
return cat;

你甚至可以选用某个 LockMode,用 SQL 的 SELECT ... FOR UPDATE 装载对象。 请查阅 API 文档以获取更多信息。

Cat cat = (Cat) sess.get(Cat.class, id, LockMode.UPGRADE);

注意,任何关联的对象或者包含的集合都不会被以 FOR UPDATE 方式返回, 除非你指定了 lock 或者 all 作为关联(association)的级联风格(cascade style)。

任何时候都可以使用 refresh() 方法强迫装载对象和它的集合。如果你使用数据库触发器功能来处理对象的某些属性,这个方法就很有用了。

sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)

How much does Hibernate load from the database and how many SQL SELECTs will it use? This depends on the fetching strategy. This is explained in 第 20.1 节 “抓取策略(Fetching strategies)”.