org.hibernate.MappingException: 未知实体:annotations.Users。

45
考虑以下层次结构:

enter image description here

以及以下类和xml:

HibernateUtil.java

package annotations;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;


/**
 * 
 * @author X3
 *
 */
public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();
    private static final String HIBERNATE_CFG = "hibernateAnnotations.cfg.xml";

    private static SessionFactory buildSessionFactory() 
    {
        Configuration cfg = new Configuration().addResource(HIBERNATE_CFG).configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().
                applySettings(cfg.getProperties()).buildServiceRegistry();
        SessionFactory sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        return sessionFactory;
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Users.java

package annotations;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.sql.Timestamp;

@Entity
@Table(name = "Users")
public class Users {

    @Id
    @GeneratedValue
    @Column(name = "USER_ID")
    private long userID;

    @Column(name = "USERNAME", nullable = false, length = 100)
    private String username;

    @Column(name = "MessageTimeDate", nullable = false)
    private java.sql.Timestamp datetime;

    @Column(name = "UserMessage", nullable = false)
    private String message;



    public Users(String username , String message)
    {
        java.util.Date date = new java.util.Date();
        this.datetime = new Timestamp(date.getTime());

        this.username = username;
        this.message = message;
    }

    public long getUserID() {
        return userID;
    }

    public void setUserID(long userID) {
        this.userID = userID;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public java.sql.Timestamp getDatetime() {
        return datetime;
    }

    public void setDatetime(java.sql.Timestamp datetime) {
        this.datetime = datetime;
    }

    public String getMessage() {
        return message;
    }

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

}

Main.java

package annotations;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class Main {

    public static void main(String[] args) {

        try
        {
               SessionFactory sf = HibernateUtil.getSessionFactory();
               Session session = sf.openSession();
               session.beginTransaction();

               Users user1 = new Users("Jack" , "Hello");
               session.save(user1);
               session.getTransaction().commit();
               session.close();
        }

        catch (Exception e)
        {
            System.out.println(e.toString());
            e.getStackTrace();
        }


    }
}

并且,hibernateAnnotations.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/CHAT_DB</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="connection.pool_size">1</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="current_session_context_class">thread</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
        <mapping class="annotations.Users"></mapping>       
    </session-factory>
</hibernate-configuration>

运行 main() 函数时,输出窗口显示以下错误信息:

org.hibernate.MappingException: Unknown entity: annotations.Users

但实体Usersannotations包中,那么问题出在哪里?


你能否将这个想过的结构提交到 Github 或其他在线源代码库中,这样我们就可以检查它并尝试运行了? - Boris Pavlović
23个回答

88

Hibernate配置文件必须定义实体类:

<mapping class="annotations.Users"/>

或者您必须明确将该类添加到配置中,使用

configuration.addClass(annotations.Users.class)
// Read mappings as a application resourceName
 // addResource is for add hbml.xml files in case of declarative approach
configuration.addResource("myFile.hbm.xml");  // not hibernateAnnotations.cfg.xml

3
这很奇怪,因为它要求我使用另一个XML文件,而Hibernate注解的整个思想是避免使用它们(当然除了使用 hibernateAnnotations.cfg.xml)。 - JAN
我已经在 hibernateAnnotations.cfg.xml 中添加了 <mapping class="annotations.Users"/>,但结果仍然相同。 - JAN
10
如果在hibernate.cfg.xml中无法使其正常工作,请尝试使用configuration.addAnnotatedClass而不是configuration.addClass。 - OneSolitaryNoob
1
@OneSolitaryNoob 这对我也起作用了。非常感谢。 - MarkyMarksFunkyBunch
你不能直接使用答案中提到的代码来运行它,你必须遵循@OneSolitaryNoob的评论。顺便说一下,谢谢。 - nomadSK25
显示剩余2条评论

17

当我试图使用注释重写我的示例(来自tutorialspoint)时,我遇到了相同的异常。这帮助了我(addAnnotatedClass()):

Configuration cfg=new Configuration(); 
cfg.addAnnotatedClass(com.tutorialspoint.hibernate.entity.Employee.class);
cfg.configure();

鉴于实体类已经进行了注释,这就是正确答案——问题中没有提到hbm.xml文件。 - James Robinson
@OneSolitaryNoob 之前也提到过,但这个方法对我有效。非常感谢。 - MarkyMarksFunkyBunch

13

我发现接受的答案对解决代码中遇到的异常没有帮助。虽然从技术上讲并不是错误,但我也不满意其他人提出的引入冗余的建议:

  • 使用configuration.addAnnotatedClass(...)以编程方式重新添加映射类
  • 创建一个hbm.xml文件和资源映射,在hibernate_test.cfg.xml中与现有注释重复
  • 使用原始问题中未提及的外部依赖项扫描已映射的类所在的包

然而,我找到了两种可能的解决方案,我想分享一下,这两种方法都独立地解决了我在自己的代码中遇到的异常。

我遇到了与@ron相同的MappingException(使用非常相似的HibernateUtil类):

public final class HibernateUtil {

    private static SessionFactory sessionFactory = null;
    private static ServiceRegistry serviceRegistry = null;

    private HibernateUtil() {}

    public static synchronized SessionFactory getSessionFactory() {
        if ( sessionFactory == null ) {
            Configuration configuration = new Configuration().configure("hibernate_test.cfg.xml");
            serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties())
                    .build();
            sessionFactory = configuration.buildSessionFactory( serviceRegistry );
        }
        return sessionFactory;
    }
// exception handling and closeSessionFactory() omitted for brevity
}

在我的hibernate_test.cfg.xml配置文件中,我有所需的类映射:

<mapping class="myPackage.Device"/>

我的Device类已经正确地使用了javax.persistence.Entity注解:

package myPackage.core;
import javax.persistence.*;

@Entity
@Table( name = "devices" )
public class Device {
    //body omitted for brevity
}

两种可能的解决方案:

第一种,我正在使用Hibernate 5.2,对于那些使用Hibernate 5的人,使用Metadata对象构建SessionFactory的解决方案应该可行。 它似乎也是Hibernate入门指南中目前推荐的本地引导机制

public static synchronized SessionFactory getSessionFactory() {
    if ( sessionFactory == null ) {

        // exception handling omitted for brevity

        serviceRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate_test.cfg.xml")
                .build();

        sessionFactory = new MetadataSources( serviceRegistry )
                    .buildMetadata()
                    .buildSessionFactory();
    }
    return sessionFactory;
}

其次,虽然在 Hibernate 5 中半废弃了 Configuration,但由于 Ron 没有说明他正在使用哪个版本的 Hibernate,因此这个解决方案对某些人也可能有价值。

我发现在实例化和配置 Configuration 和 ServiceRegistry 对象时,操作顺序非常微妙,这对我的代码产生了很大的影响。

原始顺序(在创建和配置 ServiceRegistry 之前创建和配置 Configuration):

public static synchronized SessionFactory getSessionFactory() {
    if ( sessionFactory == null ) {

        // exception handling omitted for brevity

        Configuration configuration = new Configuration().configure("hibernate_test.cfg.xml");

        serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings( configuration.getProperties() )
                .build();

        sessionFactory = configuration.buildSessionFactory( serviceRegistry );
    }
    return sessionFactory;
}

新订单ServiceRegistryConfiguration之前创建和配置):

public static synchronized SessionFactory getSessionFactory() {
    if ( sessionFactory == null ) {

        // exception handling omitted for brevity

        serviceRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate_test.cfg.xml")
                .build();

        sessionFactory = new Configuration().buildSessionFactory( serviceRegistry );
    }
    return sessionFactory;
}

冒着阅读太长没人看的风险,我还是要指出,就 hibernate_test.cfg.xml 而言,我的测试表明,configuration.getProperties() 方法仅返回 <property /> 元素,而排除了 <mapping /> 元素。这似乎与 API 文档 中对于 Configuration 的 'property' 和 'mapping' 术语的具体使用一致。我将承认,这种行为可能与 applySettings() 未能将映射数据传递给 StandardServiceRegistryBuilder 有关。但是,在构建 buildSessionFactory() 时,此映射数据应已在配置 Configuration 对象期间进行解析,并在调用时可用。因此,我怀疑这可能与将 ServiceRegistry 传递到 Configuration 对象的 buildSessionFactory() 方法时资源优先级的实现特定细节有关。
我知道这个问题已经几年了,但我希望这个答案能为某些人节省我花费时间推导的几个小时。干杯!

3
+1;我不明白为什么你的答案没有得到赞赏!它给了我一些有价值的见解,解决了我遇到的类似问题。谢谢。 - Snehasish Karmakar

7
将以下内容添加到您的xml中:

将以下内容添加到您的xml中:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
        <list>
            <value>annotations</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

我尝试了很多帖子中建议的1000种解决方案...这是唯一对我有效的。谢谢! - demian

5
如果你使用Spring的Java配置类,你可以写如下代码:
@Autowired
@Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
    LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
    sessionBuilder.addProperties(getHibernateProperties());
    sessionBuilder.addAnnotatedClasses(Foo.class);
    sessionBuilder.addAnnotatedClasses(Bar.class);
    sessionBuilder.addAnnotatedClasses(Bat.class);
    return sessionBuilder.buildSessionFactory();
}

4
好的,如果你的实体类在同一个包或子包中,你可以使用"scanPackages"方法代替一个一个地添加实体类。sessionBuilder.scanPackages("com.example.entities"); 了解更多信息:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.html - ibai

5

我曾经遇到过同样的问题。

请使用@javax.persistence.Entity代替org.hibernate.annotations.Entity


4
如果您的实体是通过注释映射的,请将以下代码添加到您的配置中:
configuration.addAnnotatedClass(theEntityPackage.EntityClassName.class);

例如:
configuration.addAnnotatedClass(com.foo.foo1.Products.class);

如果您的实体是通过 XML 文件进行映射的,请使用 addClass 而不是 addAnnotatedClass。
例如:
configuration.addClass(com.foo.foo1.Products.class);

如果您需要更多帮助,请联系我。

3

我曾经遇到同样的问题,花了近两个小时做了各种尝试,比如替换旧版的Hibernate JAR文件和更改数据库表结构等。但最终我找到了以下解决方案:

SessionFactory factory = new Configuration().configure().buildSessionFactory(); //This line to be replaced with below commented line

将上面内容替换为

//Configuration config = new Configuration().configure();
//ServiceRegistry servReg = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
//SessionFactory factory = config.buildSessionFactory(servReg);

它将会正常工作。

1
我遇到了类似的问题,添加了


 sessionFactory.setAnnotatedClasses(User.class);

这行代码有所帮助,但在此之前我遇到了


sessionFactory.setPackagesToScan(new String[] { "com.rg.spring.model" });

我不确定为什么那个不起作用。User类位于com.rg.spring.model下,请告诉我如何通过packagesToScan方法使其工作。

1

不要使用HibernateUtil.java来创建sessionfactory对象,而是应该使用以下代码:

SessionFactory sessionFactory=new AnnotationConfiguration().configure().buildSessionFactory();

因为为了避免异常,你必须在HibernateUtil.java文件中声明类对象为configuration.addAnnotatedClass(Student_Info.class);,这看起来很愚蠢,因为我们已经在hibernate.cfg.xml文件中提供了条目。
要使用AnnotationConfiguration类,您必须将一个jar添加到项目构建路径中: http://www.java2s.com/Code/Jar/h/Downloadhibernate353jar.htm

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