NHibernate官方文档中文版--只读实体类型(Read-only entities)
重点
NHIbernate处理只读对象的方式可能和你在别处看到的不同。不正确的使用方式可能造成不可预料的结果。
当一个实体是只读的时候:
- NHIbernate不会对实体的简单属性和单向关联数据检查数据是否是脏数据
- NHibernate不会对实体的简单属性和单向关联数据进行更新操作
- NHibernate不会更新只读对象的版本信息,尽管实体的简单属性和单向关联数据发生了改变
在某些情况下,NHibernate对待一些只读实体类型和费只读类型是一样的:
- Nhibernate级联操作定义在实体mapping中的关联对象
- Nhibernate在实体包含的集合被修改之后会更新它的版本信息
- 只读实体被删除
尽管一个实体不是只读的,它的管理集合对象如果包含只读实体,它还是会受到影响。
NHibernate会对只读实体进行一些优化:
- 它节约了执行时间,因为不需要对实体的简单属性和单向关联数据进行脏数据检查
- 它通过删除数据库快照来节约内存
如何使持久化对象只读
只有持久化对象才能成为只读类型。瞬时态和游离态的对象在转化成只读状态之前必须成为持久化状态。
NHibernate提供了下面的几种方法让持久化对象成为只读类型:
- 你可以将实体类型映射成不变类型,当一个不变类变成持久化状态的时候,NHibernate会自动将它变成只读类型。
- 你可以改变默认值,因此实体在加载到这个session中的时候会自动转化成只读类型。
- 你可以让一个HQL查询或者条件查询只读,因此当这个HQL或者条件查询执行,或者遍历的时候,都会自动变成只读类型。
- 你可以让一个session中的持久化实体只读。
不可变类型实体
当一个不变类实体实例转化成持久化状态的时候,NHibernate会自动让它变成只读类型。
一个不可变类可以像一个可变类一样新增和删除。
NHibernate对待一个不可变类型的持久化实体和不可变实体的只读持久化类型是一样的。唯一的不同是NHibernate不允许不可变类实体改变,即使它不是只读类型。(吐槽:真搞不懂,整个文档一直颠来倒去地重复说这句话有什么意义)
将持久化对象加载成只读类型的
注意
不可变类会被自动加载成只读类型。
要改变NHibernate加载不可变类型的时候自动将它转化成只读的默认行为,调用:
Session.DefaultReadOnly = true;
想要改变回去,调用
Session.DefaultReadOnly = false;
你可以通过使用这属性来决定当前的设定
Session.DefaultReadOnly;
如果Session.DefaultReadOnly 属性返回true,被下面方法加载的实体会自动变成只读类型:
If Session.DefaultReadOnly property returns true, entities loaded by the following are automatically made read-only:
Session.Load() 和 Session.Load<T>
Session.Get() 吧、和 Session.Get<T>
Session.Merge()
Changing this default has no effect on:改变这个默认值不会对下面实体产生影响:
persistent entities already in the session when the default was changed默认配置改变的时候已经在session中的持久化实体
persistent entities that are refreshed via Session.Refresh(); a refreshed persistent entity will only be read-only if it as read-only before refreshing通过Session.Refresh()刷新的持久化实体;一个已经被刷新的持久化实体将只会是只读的,如果在它刷新之前是只读的
persistent entities added by the application via Session.Persist(), Session.Save(), and Session.Update()Session.SaveOrUpdate()应用程序通过Session.Persist(), Session.Save(), Session.Update() 或者 Session.SaveOrUpdate()添加的持久化实体。
通过HQL/条件查询来加载只读实体(不推荐使用HQL和criteria)
Note
Entities of immutable classes are automatically loaded as read-only.
If Session.DefaultReadOnly returns false (the default) when an HQL query or criteria executes, then entities and proxies of mutable classes loaded by the query will not be read-only.
You can override this behavior so that entities and proxies loaded by an HQL query or criteria are automatically made read-only.
For an HQL query, call:
Query.SetReadOnly(true);
Query.SetReadOnly(true) must be called before Query.List(), Query.UniqueResult(), or Query.Iterate()
For an HQL criteria, call:
Criteria.SetReadOnly(true);
Criteria.SetReadOnly(true) must be called before Criteria.List(), or Criteria.UniqueResult()
Entities and proxies that exist in the session before being returned by an HQL query or criteria are not affected.
Uninitialized persistent collections returned by the query are not affected. Later, when the collection is initialized, entities loaded into the session will be read-only if Session.DefaultReadOnly returns true.
Using Query.SetReadOnly(true) or Criteria.SetReadOnly(true) works well when a single HQL query or criteria loads all the entities and intializes all the proxies and collections that the application needs to be read-only.
When it is not possible to load and initialize all necessary entities in a single query or criteria, you can temporarily change the session default to load entities as read-only before the query is executed. Then you can explicitly initialize proxies and collections before restoring the session default.
ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction(); session.DefaultReadOnly = true;
Contract contract = session.CreateQuery("from Contract where CustomerName = 'Sherman'").UniqueResult<Contract>();
NHibernate.Initialize(contract.Plan);
NHibernate.Initialize(contract.Variations);
NHibernate.Initialize(contract.Notes);
session.DefaultReadOnly = false;
...
tx.Commit();
session.Close();
If Session.DefaultReadOnly returns true, then you can use Query.SetReadOnly(false) and Criteria.SetReadOnly(false) to override this session setting and load entities that are not read-only.
让一个实体变成只读类型
想要让一个持久化实体或者代理只读,调用
To make a persistent entity or proxy read-only, call:
Session.SetReadOnly(entityOrProxy, true)
要改变一个不可变类型的只读实体或代理来让它不是只读的,调用
To change a read-only entity or proxy of a mutable class so it is no longer read-only, call:
Session.SetReadOnly(entityOrProxy, false)
重要
当一个只读实体或者代理改变成不是只读的时候,NHibernate会假设只读实体的状态和它的字段是一致的。如果不是这样的话,任何在之前或者在改变状态的时候还没有flush的改变,都会被忽略。
要抛弃未flush的改变,让持久化实体的状态和字段一致,调用:
When a read-only entity or proxy is changed so it is no longer read-only, NHibernate assumes that the current state of the read-only entity is consistent with its database representation. If this is not true, then any non-flushed changes made before or while the entity was read-only, will be ignored.
To throw away non-flushed changes and make the persistent entity consistent with its database representation, call:
Session.Refresh(entity);
想要flush在之前或者在改变状态的时候的改变,然后和数据库一致:
To flush changes made before or while the entity was read-only and make the database representation consistent with the current state of the persistent entity:
// evict the read-only entity so it is detached
session.Evict(entity); // make the detached entity (with the non-flushed changes) persistent
session.Update(entity); // now entity is no longer read-only and its changes can be flushed
s.Flush();
Read-only affect on property type只读类型对属性类型的影响
下面的表格总结了使一个实体变成只读状态之后不同属性类型会受到怎样的影响:
The following table summarizes how different property types are affected by making an entity read-only.
Table Affect of read-only entity on property types
属性/关联对象类型 | flush之后是否会改变 |
简单属性 |
不 |
单向的一对一 单向的多对一 |
不 不 |
单向的一对多 单向的多对多 |
是 是 |
双向的一对一 | 仅仅在实体不是只读的时候会改变 |
双向的一对多/多对一 集合反向 集合非反向 |
仅仅添加/删除非只读类型实体的时候会改变 是 |
双向的多对多 | 是 |
*当实体包含只读属性或者关联对象的时候是不一样的。
简单属性
当一个持久化实体是只读的时候,Nhibernate不会对简单属性进行脏检查(dirty-check )。
NHibernate不会同步简单属性的状态到数据库中。如果你使用了自动版本控制,Nhibernate不会更新版本信息。
When a persistent object is read-only, NHibernate does not dirty-check simple properties.
NHibernate will not synchronize simple property state changes to the database. If you have automatic versioning, NHibernate will not increment the version if any simple properties change.
ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction(); // get a contract and make it read-only
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true); // contract.CustomerName is "Sherman"
contract.CustomerName = "Yogi";
tx.Commit(); tx = session.BeginTransaction(); contract = session.Get<Contract>(contractId);
// contract.CustomerName is still "Sherman"
...
tx.Commit();
session.Close();
Unidirectional associations
Unidirectional one-to-one and many-to-one
当包含只读实体的时候,Nhibernate处理单向的一对一和多对一关联是相同的。
当讨论单方向的一对一和多对一关联的时候,我们会使用我们使用无方向的单向这个名词。
当包含只读实体的时候,Nhibernate不会对单向的关联进行脏检查。
如果你把只读实体的关联从单向关联变为null,或者变成其他实体,flush之后改变不会提交到数据库。
注意
如果一个不可变实体引用一个单向实体,它必须因为实体会自动被设置成只读,这些引用都不会被更新。
如果使用了自动版本控制,Nhibernate不会把单向关联的版本信息更新。
在下面的例子中,Contract有一个单向的多对一的Plan关联。Contract会级联保存和更新它的关联实体。
下面的例子战士了改变一个只读的多对一关系到null并不会影响实体数据库的信息。
NHibernate treats unidirectional one-to-one and many-to-one associations in the same way when the owning entity is read-only.
We use the term unidirectional single-ended association when referring to functionality that is common to unidirectional one-to-one and many-to-one associations.
NHibernate does not dirty-check unidirectional single-ended associations when the owning entity is read-only.
If you change a read-only entity's reference to a unidirectional single-ended association to null, or to refer to a different entity, that change will not be flushed to the database.
Note
If an entity is of an immutable class, then its references to unidirectional single-ended associations must be assigned when that entity is first created. Because the entity is automatically made read-only, these references can not be updated.
If automatic versioning is used, NHibernate will not increment the version due to local changes to unidirectional single-ended associations.
In the following examples, Contract has a unidirectional many-to-one association with Plan. Contract cascades save and update operations to the association.
The following shows that changing a read-only entity's many-to-one association reference to null has no effect on the entity's database representation.
// get a contract with an existing plan;
// make the contract read-only and set its plan to null
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true);
contract.Plan = null;
tx.Commit(); // get the same contract
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId); // contract.Plan still refers to the original plan; tx.Commit();
session.Close();
The following shows that, even though an update to a read-only entity's many-to-one association has no affect on the entity's database representation, flush still cascades the save-update operation to the locally changed association.
下面的例子展示了,尽管一个对只读实体多对一关联的更新不会影响实体的数据库信息,flush操作仍然会级联执行本地关联的save-update操作。
// get a contract with an existing plan;
// make the contract read-only and change to a new plan
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true);
Plan newPlan = new Plan("new plan");
contract.Plan = newPlan;
tx.Commit(); // get the same contract
tx = session.BeginTransaction();
contract = session.Get<Contract>(contractId);
newPlan = session.Get<Plan>(newPlan.Id); // contract.Plan still refers to the original plan;
// newPlan is non-null because it was persisted when
// the previous transaction was committed; tx.Commit();
session.Close();
Unidirectional one-to-many and many-to-many
NHibernate treats unidirectional one-to-many and many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.
NHibernate dirty-checks unidirectional one-to-many and many-to-many associations;
The collection can contain entities that are read-only, as well as entities that are not read-only.
Entities can be added and removed from the collection; changes are flushed to the database.
If automatic versioning is used, NHibernate will update the version due to changes in the collection if they dirty the owning entity.
当包含只读实体的时候,Nhibernate处理单向的一对多和多对多关联是相同的。
NHibernate会对单向的一对多和多对对关系进行脏检查。
集合可以包含只读实体,它们的改变会被flush操作提交到数据库。
如果使用了自动版本机制,Nhibernate会在修改提交后更新版本信息。
Bidirectional associations
Bidirectional one-to-one
如果一个只读实体包含了双向的一对一关联:
- NHibernate不会对关系进行脏检查
- 将关联引用到null或者其他的实体类型的修改操作不会被flush到数据库中
- 如果使用了自动版本功能,NHibernate不会因为本地数据的改变而更新版本信息
注意
如果一个实体是不可变类型,并且它包含双向的一对一关联,当这个实体第一次被创建的时候,它的引用必须被assigned。因为这个实体会自动变成只读的,而这些引用不能被更新。
当所有者不是只读的时候,NHibernate处理只读实体关联和非只读实体关联是一样的。
If a read-only entity owns a bidirectional one-to-one association:
NHibernate does not dirty-check the association.
updates that change the association reference to null or to refer to a different entity will not be flushed to the database.
If automatic versioning is used, NHibernate will not increment the version due to local changes to the association.
Note
If an entity is of an immutable class, and it owns a bidirectional one-to-one association, then its reference must be assigned when that entity is first created. Because the entity is automatically made read-only, these references cannot be updated.
When the owner is not read-only, NHibernate treats an association with a read-only entity the same as when the association is with an entity that is not read-only.
Bidirectional one-to-many/many-to-one
一个只读实体不会影响双向多对一/一对多关联,如果:
- 只读实体在一对多的一端并且使用反转集合
- 只读实体在一对多的一端并且不使用反转集合
- 一对多一段使用非反转集合并且包含只读实体
- 当一对多端使用一个反转集合
- 一个只读实体只能在集合生成的时候添加进去
- 一个只读实体只能怪通过显示的孤儿删除方式来移除出集合
A read-only entity has no impact on a bidirectional one-to-many/many-to-one association if:
the read-only entity is on the one-to-many side using an inverse collection;
the read-only entity is on the one-to-many side using a non-inverse collection;
the one-to-many side uses a non-inverse collection that contains the read-only entity
When the one-to-many side uses an inverse collection:
a read-only entity can only be added to the collection when it is created;
a read-only entity can only be removed from the collection by an orphan delete or by explicitly deleting the entity.
Bidirectional many-to-many
双向多对多
当包含只读实体的时候,Nhibernate处理双向的多对多关联是相同的。
NHibernate会对双向的多对多和多对对关系进行脏检查。
集合无论在哪端都可以包含只读实体和费只读实体。
实体可以从任意端添加或者删除,这些改变都会通过flush操作提交到数据库。
如果使用了自动版本机制,对于来自任意一端的修改,Nhibernate会在修改提交后更新版本信息。
NHibernate treats bidirectional many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.
NHibernate dirty-checks bidirectional many-to-many associations.
The collection on either side of the association can contain entities that are read-only, as well as entities that are not read-only.
Entities are added and removed from both sides of the collection; changes are flushed to the database.
If automatic versioning is used, NHibernate will update the version due to changes in both sides of the collection if they dirty the entity owning the respective collections.
NHibernate官方文档中文版--只读实体类型(Read-only entities)的更多相关文章
- NHibernate官方文档中文版——持久化类(Persistent Classes)
持久化类是一个应用程序中的类,主要用来实现业务逻辑(例如,在电商应用中的客户和订单类).持久化类,就像它的名字一样,生命周期短暂并且用来持久化的据库对象实例. 如果这些类的构造能够依照一些简单的原则, ...
- NHibernate官方文档中文版--基础ORM(Basic O/R Mapping)
映射声明 对象/关系映射在XML文件中配置.mapping文件这样设计是为了使它可读性强并且可修改.mapping语言是以对象为中心,意味着mapping是围绕着持久化类声明来建立的,而不是围绕数据表 ...
- NHibernate官方文档中文版——批量插入(Batch inserts)
A naive approach t7o inserting 100 000 rows in the database using NHibernate might look like this: 一 ...
- NHibernate官方文档中文版--ISessionFactory的配置(ISessionFactory Configuration)
由于NHibernate是被设计应用在许多不同环境中的,因此它存在很多配置参数.幸运的是,这些参数大多都有合理的默认值,而且NHibernate发布的时候伴随着一个App.config 例子(可在sr ...
- NHibernate官方文档中文版——事务和并发(Transactions And Concurrency)
NHibernate本身并不是一个数据库.它是一个轻量级的对象-关系映射工具.因此,它的事务管理代理给对应的数据库连接.如果这个连接代理了一个分布式的事务,ISession管理的操作就会自动成为整个分 ...
- NHibernate官方文档中文版--拦截器和事件(Interceptors and events)
对于应用程序来说,能够对NHibernate内部发生的事件做出响应式很有用的.这能够有助于实现一些类的功能或者扩展NHibernate的功能. 拦截器 IInterceptor接口提供了应用程序ses ...
- NHibernate官方文档中文版-框架架构(Architecture)
总体概览 一个非常高层次的NHibernate架构: 这个图展示了NHibernate使用数据库和配置信息来为应用程序提供持久化服务(和持久化对象). 我们想展示一个更加详细的运行时架构.但是NHib ...
- NHibernate官方文档——第八章 继承映射(Inheritance Mapping)
本文翻译自NHibernate官方文档NHibernate Reference Documentation 4.1. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他 ...
- 人工智能系统Google开源的TensorFlow官方文档中文版
人工智能系统Google开源的TensorFlow官方文档中文版 2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源,机器学习作为人工智能的一种类型,可以让软件根据大量的 ...
随机推荐
- es6+最佳入门实践(8)
8.Promise 8.1.什么是异步? 要理解异步,首先,从同步代码开始说 alert(1) alert(2) 像上面的代码,执行顺序是从上到下,先后弹出1和2,这种代码叫做同步代码 alert(0 ...
- mysql root设置密码 linux
成功方案 mysqld_safe --user=mysql --skip-grant-tables --skip-networking & [root@localhost ~]# mysql ...
- 在liberty中通过LTPA设置单点登录
不要忘了下面的设置,参考: https://www-01.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp. ...
- 【EOJ3654】管理孩子(贪心,二分)
题意:有一棵n个点的树,其中有k个是关键点,将树分割成若干部分,每部分至少包含一个关键点,求最大分割大小的最小值 思路: 最后特判一下f[1]的值 #include<cstdio> #in ...
- HDU2819(二分图匹配,记录过程)
Swap Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Launcher3无图标问题
MTK8382/8121平台. 机器(8寸,默认竖屏)第一次烧录完成后,以横放姿势启动,发现Launcher没有图标,而竖屏启动是没有这个问题的.在测试过程中发现,在设置中clear data后也会有 ...
- 【 Linux 网络虚拟化 】Openvswitch
openvswitch: openvswitch: 开放的虚拟交换机,虚拟交换就是利用虚拟平台,通过软件的方式形成交换机部件.跟传统的物理交换机相比,虚拟交换机同样具备众多优点: ...
- idea打包jar的多种方式,用IDEA自带的打包形式,用IDEA自带的打包形式 用Maven插件maven-shade-plugin打包,用Maven插件maven-assembly-plugin打包
这里总结出用IDEA打包jar包的多种方式,以后的项目打包Jar包可以参考如下形式: 用IDEA自带的打包形式 用Maven插件maven-shade-plugin打包 用Maven插件maven-a ...
- 错误: 在类 Main 中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application
错误: 在类 Main 中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args)否则 JavaFX 应用程序类必须扩展ja ...
- Linux下查看nginx、mysql、php的安装路径和编译参数
一:查看安装路径: 1.nginx安装路径: ps -ef | grep nginx 摁回车,将出现如下图片: master process 后面的就是 nginx的目录. 2.mysql安装路径: ...