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