为什么hibernate强制在session.get方法中进行序列化
我看到hibernate的session.get()和load()方法只接受Serializable对象。
根据我对hibernate的理解,它将生成一个SQL语句并将其发送给DBMS。 它永远不需要通过网络发送java对象。
为什么hibernate强制对我们进行序列化?
首先,Hibernate在某些签名中使用Serializable
这一事实并不意味着Hibernate 将序列化任何东西,它只是意味着如果需要,参数是可序列化的。
然后,我找不到绝对的参考,但我认为最强的论点是:
- 实体ID用作缓存的密钥(第一级,第二级),并且可以通过网络发送
一些较弱的参数(或根本不参数):
-
Session
本身可以被潜在地序列化(例如存储在HttpSession
) - Hibernate需要
entityId
的超类型(包括复合PK)
考虑到所有这些,我认为强制API的用户通过Serializable entityId
,这允许不关闭任何门并避免任何后期限制(oops,你不能激活二级缓存,因为这个pk不是Serializable
)。 这是IMO比使用Object
更好的设计决策。 说实话,我没有看到任何烦恼。
这不是真的。 来自Javadoc ,相关方法的签名是:
public Object get(Class clazz, Serializable id) ... public Object load(Class theClass, Serializable id) ...
(为简洁起见,省略了不相关的部分和其他重载版本)。
因此,要加载的实体可以是任何类,只有它的标识符需要可序列化。
根据来自Java Persistence with Hibernate的引用,实体确实不是可序列化的。 13.3.2:
持久化实例以反汇编forms存储在二级缓存中。 将反汇编视为一个类似于序列化的过程(但算法比Java序列化要快得多)。
所以我猜测标识符(在查询缓存中)也没有序列化。 我找不到任何解释为什么id
被声明为Serializable
,并且缺乏这个,我只能猜测。 API需要一个id
参数的类型,它应该是至少常用的标识符类型Number
和String
的常见超类型,除了Object
, Serializable
是唯一的选择。
我认为这是因为对缓存的支持。 当使用持久高速缓存或通过网络分发对象的任何高速缓存时,您需要有一种方法来确保对象可以以通用格式传输,在本例中是Java序列化。
坦率地说,我没有看到任何其他方式。 如果您不是定义表结构并生成插入语句以容纳对象,那么生成的SQL语句本身就是一个字符串,它会将另一个文本字符串(您的序列化数据)插入到表的字段中。 无论你在数据库中插入什么都必须是一个字符串,在这种情况下,它不能是一个具有语言相关方法的对象,除非你明确设计一个表来存储这样的数据。