如果您已经看完了三个准备,所以看此文章是没有问题的,如果没有看完请点击此处回到上一篇。
下面我们正式开始我们的七个步骤
步骤1: 装配hibernate.cfg.xml
这里我们还是使用上一个笔记的代码继续往下写,这里我们创建一个测试类HibernateTest
,在此类中有一个hibernateTest1()
方法,我这里使用单元测试,所以不需要main()
大家也可以使用main方法来调用都是也可以。
//第一步 装载hibernate.cfg.xml
//Configuration() 可是使用有参数构造,可以填写你指定的hibernate的文件名,例如hiber.cfg.xml
//如果不填写则默认装载src根目录下的hibernate.cfg.xml
Configuration configuration = new Configuration();
步骤2: 创建SessionFactory
Hibernate 3.x版本创建SessionFactory方法
//Hibernate 3.x版本创建SessionFactory方法
SessionFactory sessionFactory = configuration.buildSessionFactory();
Hibernate 4.x版本以上创建SessionFactory方法
//Hibernate 4.x版本创建SessionFactory方法
//ServiceRegistry接口:任何配置和服务都需要在该对象注册后才能有效
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
用4.x版本创建SessionFactory的时候要注意如果没有找到new ServiceRegistryBuilder()
对象要使用一下方式创建SessionFactory
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
SessionFactory sf = configuration.buildSessionFactory(sr);
Hibernate 5.x版本以上创建SessionFactory方法,我只想说呵呵,这个更变态
//Hibernate 5.x版本创建SessionFactory方法
//StandardServiceRegistry接口是一个标准服务注册接口,扩展ServiceRegistry
//使用StandardServiceRegistryBuilder()生成标准ServiceRegistry实例。
//configure() 此方法是来加载hibernate.cfg.xml文件,也就是说使用Hibernate5.x,我们可以省略第一步
//build() 此方法是用来构建StandardServiceRegistry
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
//我们在上面只是创建了一个标准的服务,但是Hibernate并不知道我们的映射有那些所以需要创建Metadata对象
//Metadata对象表示从映射来源确定orm模型,然后在通过buildSessionFactory()方法来创建SessionFactory对象
SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
步骤3: 创建Session
Session session = sessionFactory.openSession();
步骤4: 开启事务
Transaction transaction = session.getTransaction();
//事务就不需要多说了吧,oracle的增删改都离不开事务。
步骤5: 执行添加
//我们先创建一个User对象
User user = new User();
user.setId(1);
user.setName("张三");
user.setPwd("123");
//然后执行Hibernate的保存操作
session.save(user);
步骤6: 提交事务
transaction.commit();
//提交事务,做数据持久化操作
步骤7: 关闭Seession
session.close();
这里要注意 为什么不一起关闭SessionFactory呢?
因为SessionFactory是Session的工厂,整个程序创建一次就可以,我们要到Session的时候直接从工厂获取,也就是sessionFactory.openSession()
这个方法;而程序结束会自动释放SessionFactory对象所以不需要我们关闭,当然在此例程序中你也可以手动关闭。
运行程序,做测试
到此为止,我们的三个准备和七个步骤已经做完了;现在我们可以运行一下我们的程序
好的非常漂亮,一个小小的程序都给我报错了,好的上面说类为找到异常,而且提示出那个类没有找到,可以看到并不是我们自己写的类,还有继续往下看提示我们发现是因为我们的单元测试引起的,所以我们需要找到对应的架包,添加上去即可。
好吧再一次出错了
org.hibernate.MappingException: Repeated column in mapping for entity: cc.ibadboy.hibernate.hibernate2.entity.User column: name (should be mapped with insert="false" update="false")
他说我的映射异常,而且已经告诉我们是那个实体类了cc.ibadboy.hibernate.hibernate2.entity.User
,并且提示我们 column: name
, 那么我们就找这个实体类的映射文件,发现
<property name="name" type="java.lang.String" column="name" length="50" not-null="true"/>
<property name="pwd" type="java.lang.String" column="name" length="50" not-null="true"/>
发现column数据值相同,我们应该将name="pwd"
的column属性值改为pwd
<property name="name" type="java.lang.String" column="name" length="50" not-null="true"/>
<property name="pwd" type="java.lang.String" column="pwd" length="50" not-null="true"/>
我们继续调试程序,又出错了 但是这个错误非常好
可以看到 我们的程序没有用到JNDI为什么会出现这个错误呢?而且为什么提示我说
Error parsing JNDI name [foo]
这是因为我们的hibernate.cfg.xml
配置文件中的<session-factory/>
标签有一个name属性,这个name属性值为foo,当我们设置此属性Hibernate试图将这个sessionFacoty注册到JNDI中,我们项目没有用到JNDI所以会出错的。记下来看第二个问题org.hibernate.TransactionException: Transaction not successfully started
事务没有成功开启,但是我前面已经使用session.getTransaction();获取到了事务了啊,为什么失败呢?是的
session.getTransaction();
的确会获取事务,获取的是session对象所开启的事务,你的session对象都没有开启事务所以当然获取不到啊。
而这里我们要使用
session.beginTransaction();
来开启事务,这里希望大家注意一下,你虽然使用sessionFactory.openSession();
来获取了一个Session对象,但获取的仅仅只是一个Session对象而已,并没有自动的为我们开启事务。
好的两个错误解决完了,我们继续调试吧
好了调试成功可以看到输出的sql语句,1.先删除了表。2.为我们创建了新表。3.插入了我们的数据。
这里未必非要使用oracle数据库你用mysql也是可以的,前面我们也说了hibernate会为我们自动生成sql语句,生成的sql语句肯定也是对应你使用的数据库的啊。
注意
细心的读者可能会意识到,为什么我们通过main()
方法或者单元测试,也可以通过hibernate来做数据持久化,而不需要通过web容器(如:tomcat)呢?
答:因为dao、serivce层根web容器没有关系。
详细说说用到的接口和类的作用
在上面的代码中我们要到了一些接口和类,虽然在代码注释中有写到,但是我在这里在做一下总结.
1.Configuration:通过加载配置文件管理获取并管理配置信息,默认读取hibernate.cfg.xml文件;如果你需要自定义配置文件(*.cfg.xml)那么就需要使用new Configuration().configuration(*.cfg.xml)
,星号表示你自己的文件名,当然也可以传入一个File对象。
2.SessionFactory:是Session工厂类,专门帮我们来new Session的;SessionFactory也有一个缓存机制,称为二级缓存可以作用在进程或集群上。也可以说hibernate的二级缓存是SessionFactory维护的。在大多数情况下SessionFactory在整个应用程序中只创建一次。
3.Session:是我们以后用的主要对象。此对象是比较轻量级的,我们以后可以随便创建;而我们的增删改查操作,都是通过此对象来完成。注意:一个Session对象只可以由一个线程使用。我们可以想想一下,当一个浏览器发送请求到tomcat服务器的时候,tomcat会开启一个线程操作,这个线程里面调用我们的action->serivce->dao,而在dao中有我们的hibernate的一些操作,所以会启动(通过SessionFactory获取)一个Session对象。每一次浏览器发送请求到tomcat服务器的时候都会执行以上操作,所以说Session对象是属于我们一个线程中的,也可以说成Session对象由一个线程使用。
4.Transaction:用来管理事务的。我们需要在增删改的时候需要开启事务。注意:hibernate中的事务是不会自动提交的。
5.StandardServiceRegistry:一个标准服务注册接口,扩展ServiceRegistry使用StandardServiceRegistryBuilder()生成标准ServiceRegistry实例。
6.Metadata:从映射来源确定orm模型,然后在通过buildSessionFactory()方法来创建SessionFactory对象。
我个人感觉这些代码不许要特意记住,用到的时候拷贝就可以了,而且最后会通过Spring整合,整合后更用不上了。
大大的总结
1.Configuration:加载hibernate.cfg.xml文件。读取用户名、密码、方言、映射信息等。而读取的数据信息,全部放在SessionFactory对象中的。
2.SessionFactory:根据单个数据(单个hibernate.cfg.xml文件)编译后的内存镜像,编译无法改变,都是从这里来获取Session对象。我个人认为SessionFactory有点像你使用jdbc来操作数据库时的Connection对象。
3.Session:封装了JDBC的操作,通过Session中的方法,可以简化复杂的JDBC操作。我个人因为Session有点像你使用jdbc来操作数据库时的PreparedStatement对象。
资源下载
本节笔记代码我已经上传到了github上大家可以点击下载
下载链接:Hibernate3.zip