休眠 5:org.hibernate.MappingException:未知实体
Hibernate 5: org.hibernate.MappingException: Unknown entity
以下代码在 Hibernate 4.3 中运行良好,但是当我在 Hibernate 5.0 中尝试相同的代码时,它会导致以下错误:
Exception in thread "main" org.hibernate.MappingException: Unknown entity: entity.Message
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:776)
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1451)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:100)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:678)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:670)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665)
at client.Main.main(Main.java:14)
有人可以帮我理解为什么会这样吗?
以下是用于测试示例的代码:
Main.java
package client;
import org.hibernate.Session;
import util.HibernateUtil;
import entity.Message;
public class Main {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Message message = new Message( "Hello Hibernate 5" );
session.save(message);
session.getTransaction().commit();
session.close();
}
}
HibernateUtil.java
package util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
return configuration.buildSessionFactory( new StandardServiceRegistryBuilder().applySettings( configuration.getProperties() ).build() );
}
catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Message.java
package entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="message")
public class Message {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private Long id;
@Column(name="TEXT")
private String text;
public Message() {}
public Message(String text) {
this.text = text;
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/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/hello</property>
<property name="connection.username">root</property>
<property name="connection.password">pass</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping class="entity.Message"/>
</session-factory>
</hibernate-configuration>
SQL 数据库架构(RDBMS:MYSQL)
CREATE DATABASE `hello`;
USE `hello`;
CREATE TABLE `message` (
`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
`TEXT` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`ID`)
);
更新:在 Hibernate 5.0.x 中,使用标准服务注册表的配置已被弃用
相反,您应该 bootstrap 使用 元数据 :
在您的 HibernateUtil
class 中,您应该添加
private static SessionFactory buildSessionFactory() {
try {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure( "hibernate.cfg.xml" )
.build();
Metadata metadata = new MetadataSources( standardRegistry )
.getMetadataBuilder()
.build();
return metadata.getSessionFactoryBuilder().build();
}
另外,请将消息的 ID 声明 Class 更改为
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Long id;
所以hibernate可以正确使用mySql的自增,否则会抛出异常
或者,您可以在 Hibernate 5+ 中执行以下操作,让您的 SessionFactory
/Session
创建 class extend
下面的HibernateHelper
class:
包裹 com.company.hibernatehelper;</p>
<pre><code>import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateHelper {
private static SessionFactory sessionFactory = null;
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
return sessionFactory;
}
}
以下代码在 Hibernate 4.3 中运行良好,但是当我在 Hibernate 5.0 中尝试相同的代码时,它会导致以下错误:
Exception in thread "main" org.hibernate.MappingException: Unknown entity: entity.Message
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:776)
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1451)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:100)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:678)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:670)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665)
at client.Main.main(Main.java:14)
有人可以帮我理解为什么会这样吗?
以下是用于测试示例的代码:
Main.java
package client;
import org.hibernate.Session;
import util.HibernateUtil;
import entity.Message;
public class Main {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Message message = new Message( "Hello Hibernate 5" );
session.save(message);
session.getTransaction().commit();
session.close();
}
}
HibernateUtil.java
package util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
return configuration.buildSessionFactory( new StandardServiceRegistryBuilder().applySettings( configuration.getProperties() ).build() );
}
catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Message.java
package entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="message")
public class Message {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private Long id;
@Column(name="TEXT")
private String text;
public Message() {}
public Message(String text) {
this.text = text;
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/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/hello</property>
<property name="connection.username">root</property>
<property name="connection.password">pass</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping class="entity.Message"/>
</session-factory>
</hibernate-configuration>
SQL 数据库架构(RDBMS:MYSQL)
CREATE DATABASE `hello`;
USE `hello`;
CREATE TABLE `message` (
`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
`TEXT` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`ID`)
);
更新:在 Hibernate 5.0.x 中,使用标准服务注册表的配置已被弃用
相反,您应该 bootstrap 使用 元数据 :
在您的 HibernateUtil
class 中,您应该添加
private static SessionFactory buildSessionFactory() {
try {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure( "hibernate.cfg.xml" )
.build();
Metadata metadata = new MetadataSources( standardRegistry )
.getMetadataBuilder()
.build();
return metadata.getSessionFactoryBuilder().build();
}
另外,请将消息的 ID 声明 Class 更改为
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Long id;
所以hibernate可以正确使用mySql的自增,否则会抛出异常
或者,您可以在 Hibernate 5+ 中执行以下操作,让您的 SessionFactory
/Session
创建 class extend
下面的HibernateHelper
class:
包裹 com.company.hibernatehelper;</p>
<pre><code>import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateHelper {
private static SessionFactory sessionFactory = null;
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
return sessionFactory;
}
}