org.hibernate.MappingException:未知实体

23

我正在尝试学习《开始使用Hibernate第二版》,并且我在尝试使用HSQLDB来创建一个简单的工作示例时遇到了问题。

当我运行ant populateMessages时,我得到了以下结果:

[java] org.hibernate.MappingException: Unknown entity: sample.entity.Message
[java]     at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:194)
[java]     at org.apache.tools.ant.taskdefs.Java.run(Java.java:747)
...

这是我的代码:

Message.java

package sample.entity;

import org.hibernate.annotations.Entity;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
public class Message
{
    private String messageText;
    private Integer id;

    public Message( String messageText )
    {
        this.messageText = messageText;
    }

    public Message()
    {
    }

    public String getMessageText()
    {
        return messageText;
    }

    public void setMessageText(String messageText)
    {
        this.messageText = messageText;
    }

    @Id
    @GeneratedValue
    public Integer getId()
    {
        return id;
    }

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

PopulateMessages.java

package sample;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import sample.entity.Message;

import java.util.Date;

public class PopulateMessages
{
    public static void main(String[] args)
    {
        SessionFactory factory = new AnnotationConfiguration().configure().buildSessionFactory();
        Session session = factory.openSession();
        session.beginTransaction();

        Message m1 = new Message("Hibernated a  messages on " + new Date());
        session.save(m1);
        session.getTransaction().commit();
        session.close();
    }
}

build.properties

# Path to the hibernate install directory
hibernate.home=C:/hibernate/hibernate-3.5.6
# Path to the hibernate-tools install directory
hibernate.tools.home=C:/hibernate/hibernate-tools
# Path to hibernate-tools.jar relative to hibernate.tools.home
hibernate.tools.path=/plugins/org.hibernate.eclipse_3.3.1.v201006011046R-H111-GA/lib/tools
# Path to hibernate-tools hibernate libraries relative to hibernate.tools.home
hibernate.tools.lib.path=/plugins/org.hibernate.eclipse_3.3.1.v201006011046R-H111-GA/lib/hibernate
# Path to the SLF4J implementation JAR for the logging framework to use
slf4j.implementation.jar=lib/slf4j-simple-1.6.1.jar
# Path to the HSQL DB install directory
hsql.home=C:/hsqldb

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">
jdbc:hsqldb:file:testdb;shutdown=true
</property>
<property name="hibernate.connection.driver_class">
org.hsqldb.jdbcDriver
</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.pool_size">0</property>
<property name="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</property>
<property name="hibernate.show_sql">false</property>
<!-- "Import" the mapping resources here -->
<mapping class="sample.entity.Message"/>
</session-factory>
</hibernate-configuration>

build.xml

<project name="sample">
    <property file="build.properties"/>
    <property name="src" location="src"/>
    <property name="bin" location="bin"/>
    <property name="sql" location="sql"/>
    <property name="hibernate.tools"
              value="${hibernate.tools.home}${hibernate.tools.path}"/>
    <path id="classpath.base">
        <pathelement location="${src}"/>
        <pathelement location="${bin}"/>
        <pathelement location="${hibernate.home}/hibernate3.jar"/>
        <pathelement location="${slf4j.implementation.jar}"/>
        <fileset dir="${hibernate.home}/lib" includes="**/*.jar"/>
        <pathelement location="${hsql.home}/lib/hsqldb.jar"/>
  <fileset dir="./lib" includes="**/*.jar"/>
    </path>
<path id="classpath.tools">
    <path refid="classpath.base"/>
    <pathelement
            location="${hibernate.tools.home}/${hibernate.tools.lib.path}/commons-logging-1.0.4.jar"/>
    <pathelement
            location="${hibernate.tools}/freemarker.jar"/>
    <pathelement
            location="${hibernate.tools}/hibernate-tools.jar"/>
</path>
<taskdef name="htools"
         classname="org.hibernate.tool.ant.HibernateToolTask"
         classpathref="classpath.tools"/>
<target name="exportDDL" depends="compile">
    <mkdir dir="${sql}"/>
    <htools destdir="${sql}">
        <classpath refid="classpath.tools"/>
        <annotationconfiguration
                configurationfile="${src}/hibernate.cfg.xml"/>
        <hbm2ddl drop="true" outputfilename="sample.sql"/>
    </htools>
</target>
<target name="compile">
    <javac srcdir="${src}" destdir="${bin}" classpathref="classpath.base"/>
</target>
<target name="populateMessages" depends="compile">
    <java classname="sample.PopulateMessages" classpathref="classpath.base"/>
</target>
<target name="listMessages" depends="compile">
    <java classname="sample.ListMessages" classpathref="classpath.base"/>
</target>


1
+1 对于详细的问题描述。我也遇到了同样的问题,看了你的 hibernate.cfg.xml 文件后,发现了我的问题所在。 - apines
12个回答

36

您的实体未正确注释,必须使用 @javax.persistence.Entity 注解。您可以使用 Hibernate 扩展 @org.hibernate.annotations.Entity 来扩展 JPA 的功能,但是 Hibernate 注解不是替换品,而是补充。

因此,请将代码更改为:

<b>import javax.persistence.Entity;</b>
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
public class Message { 
    ...  
}

参考资料


啊,实体必须使用Hibernate注解这一点是新的对我来说(我从未使用过Hibernate注解)。我注意到了这一点(请看我的更新),但不确定它是否是答案 :) (+1) - Bozho
@Bozho 不能确定笔记的内容,但我确信Hibernate注解一直都是一种补充而非替代。对你的更新点赞+1。 - Pascal Thivent
我来测试一下。我永远也不会发现这个问题。 - Stefan Kendall
@Stefan 嗯,这是一个恶性问题。在与 Bozho 聊天后进行了 N 次代码扫描时,我检测到了它的存在。事实上,写这些东西给了我一个关于问题可能出现的想法。 - Pascal Thivent
但是,如果所需的实体类来自另一个库怎么办?有没有绕过使用 @Entity 的方法? - zygimantus

12
你需要在AnnotationConfiguration上调用.addAnnotatedClass(Message.class)
如果您想要自动发现实体,请使用EntityManager(JPA)。
参考
更新:看起来您已经在hibernate.cfg.xml中列出了该类。因此,自动发现是不必要的。另外,尝试使用javax.persistence.Entity

2
不,OP 不应该这样做,实体在 hibernate.cfg.xml 中已经声明了。 - Pascal Thivent
@Pascal Thivent 嗯,我漏掉了那行。那很奇怪,因为默认情况下 Configuration.configure() 会查找 hibernate.cfg.xml 文件。 - Bozho
是的,我同意,这很奇怪。我本来期望事情会完全失败(.cfg.xml文件找不到),而不是“部分”失败。激活日志记录可能有所帮助,但我太懒了,不想设置Ant构建来重现 :) - Pascal Thivent
哈哈,我发现问题了 :) - Pascal Thivent
@Pascal Thivent 是谁? :) - Bozho
发布(火狐浏览器出了点问题,不得不重启,喝杯咖啡等等)。 - Pascal Thivent

1
如果您在使用带有Entity注释的实体的SpringBoot应用程序中遇到此异常,可能是因为Spring不知道在哪里扫描实体。要明确指定包,请添加以下内容。
@SpringBootApplication
@EntityScan({"model.package.name"})
public class SpringBootApp {...}

注意:如果您的模型类与带有SpringBootApplication注释的类位于同一或子包中,则无需显式声明EntityScan,默认情况下它将进行扫描。

1

如果您正在使用Spring Boot应用程序,请使用以下代码行。将其添加到Spring Boot主类中:@EntityScan(basePackageClasses=YourClassName.class)


1

在Spring Boot应用程序中使用以下代码行。

@EntityScan(basePackageClasses=YourClassName.class)


0

使用import javax.persistence.Entity;而不是import org.hibernate.annotations.Entity;


0

您可以通过在 Application.java 上添加以下注释来启用实体扫描:

@EntityScan(basePackageClasses=YourEntityClassName.class)

或者您可以在会话工厂中设置 packageToScan。

sessionFactory.setPackagesToScan(“com.all.entity”);


0

0

当我切换到AnnotationSessionFactoryBean时,我遇到了同样的问题。之前我使用的是entity.hbm.xml

我发现我的类缺少了以下注释,在我的情况下解决了这个问题:

@Entity
@Table(name = "MyTestEntity")
@XmlRootElement

0
检查实体是否在 hibernate.cfg.xml 中定义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接