🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 10.3\. 装载对象 如果你知道某个实例的持久化标识(identifier),你就可以使用`Session`的`load()`方法 来获取它。 `load()`的另一个参数是指定类的.class对象。 本方法会创建指定类的持久化实例,并从数据库加载其数据(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) ``` 此处通常会出现一个重要问题: Hibernate会从数据库中装载多少东西?会执行多少条相应的SQL`SELECT`语句? 这取决于_抓取策略(fetching strategy)_,会在[第 19.1 节 “ 抓取策略(Fetching strategies) ”](../Text/pr01_split_000.html#performance-fetching "19.1\. 抓取策略(Fetching strategies) ")中解释。