为啥当我使用hibernate时这个类应该实现java.io.Serializable?

Posted

技术标签:

【中文标题】为啥当我使用hibernate时这个类应该实现java.io.Serializable?【英文标题】:Why this class should implement java.io.Serializable when I using hibernate?为什么当我使用hibernate时这个类应该实现java.io.Serializable? 【发布时间】:2011-06-22 12:59:04 【问题描述】:

此异常仅在使用 Tweet Class 时发生。我找不到我应该使用Serializable 的原因。我自己在GeneticMessage.hbm.xml 中进行了映射。 Tweet Class 中的所有类型(long 和 Date)都是 Hibernate 中的基本类型(我认为是这样)。

实际上,只要实现异常中提到的Serializable for Tweet就可以解决这个问题。但我还是想知道原因。

方法

域域=(域)对象[0]; 查询 q = session.createQuery("FROM PreprocessedMessage WHERE domain = ?"); q.setEntity(0, domain); 返回 q.list(); // 这一行

例外:

java.lang.ClassCastException: idv.petrie.prtm.model.Tweet 不能转换为 java.io.Serializable
    org.hibernate.type.CollectionType.getKeyOfOwner(CollectionType.java:381)
    org.hibernate.type.CollectionType.resolve(CollectionType.java:425)
    org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
    org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
    org.hibernate.loader.Loader.doQuery(Loader.java:857)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    org.hibernate.loader.Loader.doList(Loader.java:2533)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    org.hibernate.loader.Loader.list(Loader.java:2271)
    org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
    org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
    org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
    org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
    org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    idv.petrie.prtm.model.helper.PreprocessedMessageHelper$3.execute(PreprocessedMessageHelper.java:66)
    idv.petrie.prtm.util.ModelHelper.execute(ModelHelper.java:36)
    idv.petrie.prtm.model.helper.PreprocessedMessageHelper.findMessageByDomain(PreprocessedMessageHelper.java:69)
    idv.petrie.prtm.servlet.MessageEvaluationServlet.doGet(MessageEvaluationServlet.java:44)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

PreprocessedMessage.java

包 idv.petrie.prtm.model;

导入 java.util.Collection;
导入 java.util.HashSet;
导入 java.util.Set;

公共类 PreprocessedMessage 扩展 GeneticMessage 

    私人GeneticMessage消息;

    私有设置依赖项;

    私有集令牌;

    公共预处理消息()
        极好的();
    

    public PreprocessedMessage(GeneticMessage 消息,字符串内容) 
        这();
        this.setMessage(消息);
        this.setContent(内容);
        this.setDomain(message.getDomain());
    

    公共预处理消息(遗传消息消息)
        这(消息,message.getContent());
    

    公共 PreprocessedMessage(GeneticMessage 消息,
            设置依赖)
        这条信息);
        this.dependencies = 依赖项;
    

    公共静态集合 convertToCollection(
            收集消息)
        收集结果 = new HashSet();
        对于(GeneticMessage 消息:消息)
            result.add(new PreprocessedMessage(message));
        
        返回结果;

    

    公共无效setMessage(GeneticMessage消息)
        this.message = 消息;
    

    公共遗传信息 getMessage() 
        返回消息;
    

    公共设置 getDependencies() 
        返回依赖项;
    

    公共无效 setDependencies(设置依赖项)
        对于(依赖项 d:依赖项)
            d.setMessage(this);
        
        this.dependencies = 依赖项;
    

    公共集合 getTokens() 
        返回代币;
    

    公共无效 setTokens(设置令牌)
        对于(令牌 t:令牌)
            t.setMessage(this);
        
        this.tokens = 代币;
    



Tweet.java

包 idv.petrie.prtm.model;

导入 java.util.Date;

公共类推文扩展GeneticMessage 

    私人长推文ID;

    私人创建日期在;

    私人长 fromUserId;

    公共推文()
        极好的();
    

    公共推文(字符串内容)
        这();
        设置内容(内容);
    

    公共日期 getCreatedAt() 
        返回创建时间;
    

    公共无效 setCreatedAt(创建日期)
        this.createdAt = createdAt;
    

    公共长 getFromUserId() 
        从用户ID返回;
    

    公共无效 setFromUserId(long fromUserId) 
        this.fromUserId = fromUserId;
    

    公共无效 setTweetId(长推文 ID)
        this.tweetId = tweetId;
    

    公共长 getTweetId() 
        返回推文ID;
    


GeneticMessage.java

包 idv.petrie.prtm.model; 导入 java.util.Date; 公共类 GeneticMessage 实现 Comparable 公共枚举状态 新的(0),预处理的(1); 私人 int id; 私人状态(int id) 这个.id = id; 公共 int getId() 返回标识; 私人长ID; 私人修改日期; 私有字符串内容; 私人状态状态; 私有域域; 公共遗传消息() setModifiedAt(); 设置状态(状态。新); 公共长 getId() 返回标识; 公共无效setId(长ID) 这个.id = id; 公共字符串 getContent() 返回内容; 公共无效 setContent(字符串内容) this.content = 内容; 公共无效 setModifiedAt() this.modifiedAt = new Date(); 公共日期 getModifiedAt() 返回修改后; 公共无效setStatus(状态状态) this.status = 状态; 公共状态 getStatus() 返回状态; 公共无效 setDomain(域域) this.domain = 域; 公共域 getDomain() 返回域; 公共 int compareTo(GeneticMessage o) 字符串内容 = this.getContent(); 字符串 anotherContent = o.getContent(); return content.compareTo(anotherContent); 公共无效 setModifiedAt(修改日期) this.modifiedAt = modifiedAt;

GeneticMessage.hbm.xml

<code>
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping 
 PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <typedef class="idv.petrie.prtm.model.GeneticMessage.Status"
        name="Status">
        <param name="enumClassName">idv.petrie.prtm.model.GeneticMessage.Status</param>
        <param name="identifierMethod">getId</param>
    </typedef>

    <class name="idv.petrie.prtm.model.GeneticMessage">
        <id name="id">
            <generator class="native" />
        </id>
        <property name="modifiedAt" />
        <property name="content" />
        <property name="status" />
        <many-to-one name="domain" class="idv.petrie.prtm.model.Domain"
            cascade="all" outer-join="true" />

        <joined-subclass name="idv.petrie.prtm.model.PreprocessedMessage">
            <key />
            <many-to-one name="message" class="idv.petrie.prtm.model.GeneticMessage"
                outer-join="true" />
            <set name="dependencies" cascade="save-update" inverse="true">
                <key property-ref="message" />
                <one-to-many class="idv.petrie.prtm.model.Dependency" />
            </set>
            <set name="tokens" cascade="save-update" inverse="true">
                <key property-ref="message" />
                <one-to-many class="idv.petrie.prtm.model.Token" />
            </set>
        </joined-subclass>

        <joined-subclass name="idv.petrie.prtm.model.Tweet">
            <key />
            <property name="tweetId" unique="true" />
            <property name="createdAt" />
            <property name="fromUserId" />
        </joined-subclass>
    </class>
</hibernate-mapping>
</code>

【问题讨论】:

[类似问题已被问及回答..][1] [1]:***.com/questions/2020904/… 对不起,我还是听不懂。是“来自 PreprocessedMessage WHERE 域 = 吗?”混合 HQL 和原生 SQL 查询?我刚刚编辑了我的问题以使其清楚。 q.setEntity(0, domain);这条线导致了问题。域类应该是可序列化的。 我明白你的意思。但是 domain 是在另一个 hbm.xml 中定义的(也就是 Domain.hbm.xml,这里没有贴出代码)。并且异常要求我为 Tweet 实现 Serializable? 你知道为什么有些实体需要可序列化而有些不需要吗? 【参考方案1】:

这个问题已经过去了 6 年,但是对于那些偶然发现这个问题的人来说,这是我的 5 美分:

tweetId 可能不是Tweet 的主键(尽管我无法从 OP 给出的配置 xml 中看出这一点),这就是为什么它是唯一需要可序列化的类的原因。它被报告为 Hibernate 中的一个错误。 (https://hibernate.atlassian.net/browse/HHH-7668)。

总结:如果要在 Hibernate 对象之间建立关系,只需使用主键作为链接列。否则,使链接对象可序列化,这也可以。 :-)

【讨论】:

我有同样的问题,我添加了可序列化但它不起作用【参考方案2】:

HQL 或 SQL 函数中的所有参数都必须是可序列化的。如果不是,Hibernate 肯定也没有办法将其传递给数据库层。

【讨论】:

但我没有为用作参数的其他类实现 Serializable 其实所有类。这意味着GeneticMessage,Tweet,PreprocessedMessage,Token,Dependency等......

以上是关于为啥当我使用hibernate时这个类应该实现java.io.Serializable?的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我使用 Spring-Data 时 Maven 会添加 Hibernate Jars

当我应该在 boostrap 轮播中添加活动类时,为啥要在左边添加类

为啥我的 ja.lproj 不显示日语?

为啥在这个 Hibernate 映射中使用 @ManyToOne 而不是 @OneToOne?

当我所做的只是一个列表时,为啥 Hibernate 会删除我的集合条目?

为啥当我将 hbm2ddl.auto 设置为创建时,Hibernate 会抛出 SQLGrammarException 说表/视图不存在?