企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 4.4\. 动态模型(Dynamic models) _注意,以下特性在当前处于试验阶段,将来可能会有变化。_ 运行期的持久化实体没有必要一定表示为像POJO类或JavaBean对象那样的形式。Hibernate也支持动态模型 (在运行期使用`Map`的`Map`)和象DOM4J的树模型那 样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。 Hibernate默认工作在普通POJO模式。你可以使用配置选项`default_entity_mode`, 对特定的`SessionFactory`,设置一个默认的实体表示模式。 (参见[表 3.3 “ Hibernate配置属性 ”](../Text/pr01_split_000.html#configuration-optional-properties "表 3.3\. Hibernate配置属性 ")。) 下面是用`Map`来表示的例子。首先,在映射文件中,要声明 `entity-name`来代替一个类名(或作为一种附属)。 ``` <hibernate-mapping> <class entity-name="Customer"> <id name="id" type="long" column="ID"> <generator class="sequence"/> </id> <property name="name" column="NAME" type="string"/> <property name="address" column="ADDRESS" type="string"/> <many-to-one name="organization" column="ORGANIZATION_ID" class="Organization"/> <bag name="orders" inverse="true" lazy="false" cascade="all"> <key column="CUSTOMER_ID"/> <one-to-many class="Order"/> </bag> </class> </hibernate-mapping> ``` 注意,虽然是用目标类名来声明关联的,但是关联的目标类型除了是POJO之外,也可以 是一个动态的实体。 在使用`dynamic-map`为`SessionFactory` 设置了默认的实体模式之后,可以在运行期使用`Map`的 `Map`。 ``` Session s = openSession(); Transaction tx = s.beginTransaction(); Session s = openSession(); // Create a customer Map david = new HashMap(); david.put("name", "David"); // Create an organization Map foobar = new HashMap(); foobar.put("name", "Foobar Inc."); // Link both david.put("organization", foobar); // Save both s.save("Customer", david); s.save("Organization", foobar); tx.commit(); s.close(); ``` 动态映射的好处是,变化所需要的时间少了,因为原型不需要实现实体类。然而,你无法进行 编译期的类型检查,并可能由此会处理很多的运行期异常。幸亏有了Hibernate映射,它使得数 据库的schema能容易的规格化和合理化,并允许稍后在此之上添加合适的领域模型实现。 实体表示模式也能在每个`Session`的基础上设置: ``` Session dynamicSession = pojoSession.getSession(EntityMode.MAP); // Create a customer Map david = new HashMap(); david.put("name", "David"); dynamicSession.save("Customer", david); ... dynamicSession.flush(); dynamicSession.close() ... // Continue on pojoSession ``` 请注意,用`EntityMode`调用`getSession()`是在 `Session`的API中,而不是`SessionFactory`。 这样,新的`Session`共享底层的JDBC连接,事务,和其他的上下文信 息。这意味着,你不需要在第二个`Session`中调用 `flush()`和`close()`,同样的,把事务和连接的处理 交给原来的工作单元。 关于XML表示能力的更多信息可以在[第 18 章 _XML映射_](../Text/pr01_split_000.html "第 18 章 XML映射")中找到。