一、Hibernate报错org.hibernate.MappingException: Unknown entity: XXX的原因
有新手刚学到Hibernate时会看着视频或书来学习,但是视频里和书本上的代码都是几年前的Hibernate版本大部分低于Hibernate5.X,所以会出现一些错误。比如:
信息: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
org.hibernate.MappingException: Unknown entity: com.hibtest1.entity.Users
当你仔细检查过后没有发现错误(照着书敲了一遍代码),其实是版本问题导致的错误。
(1)//Hibernate4.X版本的写法
//生成一个注册机对象
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
//使用注册机机对象serviceRegistry创建sessionFactory
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
(2) //Hibernate5.X版本的写法
//生成一个注册机对象
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
//使用注册机机对象serviceRegistry创建sessionFactory
sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
(3)两者的工作原理差别解析:
Hibernate4版本的SessionFactory实例构建的步骤是这样的(也是很多学习资料的通用范本):
//Configuration就是代表着hibernate的那个xml配置文件对象,如果configure方法中没有参数的话,默认是就是hibernate.cfg.xml。
Configuration conf = new Configuration().configure();
//选择Hibernate.cfg.xml
Configuration conf = new Configuration().configure(“/Hibernate.cfg.xml”);
//服务注册,这是使用创建者模式,根据配置文件中的配置字段来构建注册服务(这应该是hibernate架构中注册服务的通用流程)。
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().
applySettings(conf.getProperties()).build();
//使用实例化好了的注册服务,使用Configuration中的工厂模式实例化了SessionFactory
SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
如果你用的是Hibernate4的版本,这样做完全OK的,运行的时候不会报MappingException。
但是如果你使用Hibernate5的版本,就会报错。那么Hibernate5应该怎样构建SessionFactory呢,如下:
//和V4版本比,V5版本看不到configure对象了。直接使用创建者模式构建出了标准服务注册对象
//1. 配置类型安全的准服务注册类,这是当前应用的单例对象,不作修改,所以声明为final
//在configure(“cfg/hibernate.cfg.xml”)方法中,如果不指定资源路径,默认在类路径下寻找名为hibernate.cfg.xml的文件
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure(“cfg/hibernate.cfg.xml”).build();
//2. 根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
二、初学Hibernate的源代码例子(能运行):
环境:(64bit)win10+MyEclipse2016+JDK1.8
依赖jar包:从官网上下载的Hibernate(版本为:5.2.12.Final)包和MySQL连接驱动包(版本为:5.1.7)
例子结构截图:
(1)HibernateSessionFactory.java
package com.hibtest1;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateSessionFactory {
//指定Hibernate配置文件路径
private static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";
//创建ThreadLocal对象
private static final ThreadLocal sessionThreadLocal=new ThreadLocal();
//创建Configuration对象
private static Configuration configuration = new Configuration();
//定义SessionFactory对象
private static SessionFactory sessionFactory;
//定义configFile属性并赋值
private static String configFile = CONFIG_FILE_LOCATION;
static{
try{
//读取配置文件hibernate.cfg.xml
configuration.configure();
/*
* Hibernate4.X版本的写法,不能运行有如下错误:
* 信息: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
* org.hibernate.MappingException: Unknown entity: com.hibtest1.entity.Users
*
* //生成一个注册机对象
* ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
*
* sessionFactory = configuration.buildSessionFactory(serviceRegistry);
*/
//Hibernate5.X版本的写法
//使用注册机机对象serviceRegistry创建sessionFactory//生成一个注册机对象
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
//使用注册机机对象serviceRegistry创建sessionFactory
sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
}catch(HibernateException e){
e.printStackTrace();
}
}
//创建无参的HibernateSessionFactory构造方法
private HibernateSessionFactory(){}
//获得SessionFactory对象
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
//重建SessionFActory
public static void rebuildSessionFactory(){
synchronized (sessionFactory) {
try{
configuration.configure(configFile);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
//使用注册机机对象serviceRegistry创建sessionFactory
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}catch(HibernateException e){
e.printStackTrace();
}
}
}
//获取Session对象
public static Session getSession(){
//获得ThreadLocal对象管理的Session对象
Session session = (Session)sessionThreadLocal.get();
try{
//判断Session对象是否已经存在或知否打开
if(session == null || !session.isOpen()){
//如果Session对象为空后未打开,再判断sessionFactory对象是否为空
if(sessionFactory == null){
//如果SessionFactory为空,则创建SessionFactory
rebuildSessionFactory();
}
//如果SessionFactory不为空,则打开Session
session = (sessionFactory != null)?sessionFactory.openSession():null;
sessionThreadLocal.set(session);
}
}catch(HibernateException e){
e.printStackTrace();
}
return session;
}
//关闭Session对象
public static void closeSession(){
Session session = (Session)sessionThreadLocal.get();
sessionThreadLocal.set(null);
try{
if(session != null && session.isOpen()){
session.close();
}
}catch(HibernateException e){
e.printStackTrace();
}
}
//configFile属性的set方法
public static void setConfigFile(String configFile){
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}
//configuration属性的get方法
public static Configuration getConfiguration(){
return configuration;
}
}
package com.hibtest1.entity;
import java.io.Serializable;
public class Users implements Serializable {
private Integer id;
private String loginName;
private String loginPwd;
private String name;
private String address;
private String phone;
private String mail;
public Users(){ //空构造函数
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getLoginPwd() {
return loginPwd;
}
public void setLoginPwd(String loginPwd) {
this.loginPwd = loginPwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
}
(3)Users.hbm.xml
(4)TestAddUser.java
package com.hibtest1;
import org.hibernate.*;
import com.hibtest1.entity.Users;
public class TestAddUser {
public static void main(String[] args) {
new TestAddUser().addUser();
}
private void addUser(){
//创建实体类(瞬态对象)
Users user = new Users();
user.setLoginName("zhangsan");
user.setLoginPwd("123456");
user.setName("张三");
user.setAddress("江苏南京");
user.setPhone("0123456789");
user.setMail("[email protected]");
Session session = HibernateSessionFactory.getSession();
Transaction tx = null;
try{
//开始一个事物
tx = session.beginTransaction();
//调用save方法持久化user对象,之后user对象转变为持久状态
session.save(user);
//提交事物,向数据库中插入一个新事物
tx.commit();
}catch(Exception e){
if(tx != null){
tx.rollback(); //事物回滚
}
e.printStackTrace();
}finally {
HibernateSessionFactory.closeSession(); //关闭session
//此时,user对象处于托管态
}
}
}
(5)hibernate.cfg.xml
true
bookshop
jdbc:mysql://localhost:3306/bookshop
root
123456
com.mysql.jdbc.Driver
org.hibernate.dialect.MySQLDialect
三、总结
以上就是一个简单的例子,对于学习Hibernate入门的新手来说很适合,而且使用了配置文件,没有使用注解的方式。
ps:如果有新手想要相应的jar包和该例子的源代码,请评论去留言,我会给大家分享的!同时,如果代码有错误的地方或者有更好的想法,也可以在评论去留言
欢迎大家交流,共同学习进步!