一、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<Session> sessionThreadLocal=new ThreadLocal<Session>(); //创建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; } }
(2)Users.java
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
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hibtest1.entity.Users" table="users" catalog="bookshop"> <id name="id" type="java.lang.Integer"> <column name="Id" /> <generator class="native"></generator> </id> <property name="loginName" type="java.lang.String"> <column name="LoginName" length="50" /> </property> <property name="loginPwd" type="java.lang.String"> <column name="LoginPwd" length="16" /> </property> <property name="name" type="java.lang.String"> <column name="Name" length="16" /> </property> <property name="address" type="java.lang.String"> <column name="Address" length="16" /> </property> <property name="phone" type="java.lang.String"> <column name="Phone" length="16" /> </property> <property name="mail" type="java.lang.String"> <column name="Mail" length="16" /> </property> </class> </hibernate-mapping>(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
<?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="show_sql">true</property> <property name="myeclipse.connection.profile">bookshop</property> <property name="connection.url"> jdbc:mysql://localhost:3306/bookshop </property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <mapping resource="com/hibtest1/entity/Users.hbm.xml" /> </session-factory> </hibernate-configuration>
(6)运行结果截图:
(7)Navicat视图下数据库里的数据截图:
三、总结
以上就是一个简单的例子,对于学习Hibernate入门的新手来说很适合,而且使用了配置文件,没有使用注解的方式。
ps:如果有新手想要相应的jar包和该例子的源代码,请评论去留言,我会给大家分享的!同时,如果代码有错误的地方或者有更好的想法,也可以在评论去留言
欢迎大家交流,共同学习进步!