为什么这个类在我使用 hibernate 时应该实现 java.io.Serializable?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4918262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:37:06  来源:igfitidea点击:

Why this class should implement java.io.Serializable when I using hibernate?

javahibernate

提问by Petrie Wong

This exception only happened when Tweet Classwas used. I cannot find the reason why I should use Serializable. I did the mapping myself in GeneticMessage.hbm.xml. All the types (long & Date) in Tweet Class are basic type in Hibernate (I think so).

此异常仅在Tweet Class使用时发生。我找不到我应该使用Serializable. 我自己在GeneticMessage.hbm.xml. Tweet Class 中的所有类型(long & Date)都是 Hibernate 中的基本类型(我认为是)。

Actually, the problem can be solved by just implementing Serializable for Tweet as mentioned in the Exception. But I still want to know the reason.

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

Method

方法

Domain domain = (Domain) objects[0];
Query q = session.createQuery("FROM PreprocessedMessage WHERE domain = ?");
q.setEntity(0, domain);
return q.list(); // this line

Exception:

例外:

java.lang.ClassCastException: idv.petrie.prtm.model.Tweet cannot be cast to 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.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

预处理消息.java

package idv.petrie.prtm.model;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class PreprocessedMessage extends GeneticMessage {

    private GeneticMessage message;

    private Set dependencies;

    private Set tokens;

    public PreprocessedMessage() {
        super();
    }

    public PreprocessedMessage(GeneticMessage message, String content) {
        this();
        this.setMessage(message);
        this.setContent(content);
        this.setDomain(message.getDomain());
    }

    public PreprocessedMessage(GeneticMessage message) {
        this(message, message.getContent());
    }

    public PreprocessedMessage(GeneticMessage message,
            Set dependencies) {
        this(message);
        this.dependencies = dependencies;
    }

    public static Collection convertToCollection(
            Collection messages) {
        Collection result = new HashSet();
        for (GeneticMessage message : messages) {
            result.add(new PreprocessedMessage(message));
        }
        return result;

    }

    public void setMessage(GeneticMessage message) {
        this.message = message;
    }

    public GeneticMessage getMessage() {
        return message;
    }

    public Set getDependencies() {
        return dependencies;
    }

    public void setDependencies(Set dependencies) {
        for (Dependency d : dependencies) {
            d.setMessage(this);
        }
        this.dependencies = dependencies;
    }

    public Collection getTokens() {
        return tokens;
    }

    public void setTokens(Set tokens) {
        for (Token t : tokens) {
            t.setMessage(this);
        }
        this.tokens = tokens;
    }

}

Tweet.java

推文.java

package idv.petrie.prtm.model;

import java.util.Date;

public class Tweet extends GeneticMessage {

    private long tweetId;

    private Date createdAt;

    private long fromUserId;

    public Tweet() {
        super();
    }

    public Tweet(String content) {
        this();
        setContent(content);
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public long getFromUserId() {
        return fromUserId;
    }

    public void setFromUserId(long fromUserId) {
        this.fromUserId = fromUserId;
    }

    public void setTweetId(long tweetId) {
        this.tweetId = tweetId;
    }

    public long getTweetId() {
        return tweetId;
    }

}

GeneticMessage.java

遗传信息.java

package idv.petrie.prtm.model;

import java.util.Date;

public class GeneticMessage implements Comparable {

    public enum Status {
        NEW(0), PREPROCESSED(1);
        private int id;

        private Status(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }
    }

    private long id;

    private Date modifiedAt;

    private String content;

    private Status status;

    private Domain domain;

    public GeneticMessage() {
        setModifiedAt();
        setStatus(Status.NEW);
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setModifiedAt() {
        this.modifiedAt = new Date();
    }

    public Date getModifiedAt() {
        return modifiedAt;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public Status getStatus() {
        return status;
    }

    public void setDomain(Domain domain) {
        this.domain = domain;
    }

    public Domain getDomain() {
        return domain;
    }

    public int compareTo(GeneticMessage o) {
        String content = this.getContent();
        String anotherContent = o.getContent();
        return content.compareTo(anotherContent);
    }

    public void setModifiedAt(Date modifiedAt) {
        this.modifiedAt = modifiedAt;
    }
}

GeneticMessage.hbm.xml

遗传信息.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>

回答by Javi Armendáriz

6 years has passed since this question, but here's my 5 cents for those who stumble upon this problem:

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

It's possible (although I cannot tell it from the config xmls given by the OP) that tweetIdis not the primary key of Tweetand that's why it's the only class that requires to be Serializable. It is reported as a bug in Hibernate. (https://hibernate.atlassian.net/browse/HHH-7668).

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

In Summary: if you want to make a relation between Hibernate objects, just use the primary key as the link column. Otherwise, make the linked object Serializable and that'll work as well. :-)

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

回答by Daniel

All parameters in HQL or SQL functions must be Serializable. If it is not, there is certainly also no way for Hibernate to pass it to the database layer.

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