什么是Hibernate?
Hibernate是一个基于jdbc的开源的持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑。
Hibernate的主页为:http://www.hibernate.org/。
Hibernate的下载地址为:http://hibernate.org/orm/downloads/。
HibernateTools的下载地址为:http://www.jboss.org/tools/download/。在Eclipse中如何安装Hibernate Tools插件,请参看Eclipse在线配置Hibernate Tools。
本人使用的是hibernate-release-4.3.11.Final。
Hibernate,翻译过来是冬眠的意思,正好现在已经进入秋季,世间万物开始准备冬眠了。其实对于对象来说就是持久化。
扫盲--------------------------------------------------------------------------------------------------------
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
持久化是将程序数据在持久状态和瞬时状态间转换的机制。
JDBC就是一种持久化机制。文件IO也是一种持久化机制。
日常持久化的方法:
1、将鲜肉冷藏,吃的时候再解冻的方法也是。
2、将水果做成罐头的方法也是。
结束----------------------------------------------------------------------------------------------------------
我们从三个角度理解一下Hibernate:
一、Hibernate是对JDBC进一步封装
原来没有使用Hiberante做持久层开发时,存在很多冗余,如:各种JDBC语句,connection的管理,所以出现了Hibernate把JDBC封装了一下,我们不用操作数据,直接操作它就行了。
二、我们再从分层的角度来看
我们知道非常典型的三层架构:表示层,业务层,还有持久层。Hiberante也是持久层的框架,而且持久层的框架还有很多,比如:IBatis,Nhibernate,JDO,OJB,EJB等等。
三、Hibernate是开源的一个ORM(对象关系映射)框架。
ORM,即Object-Relational Mapping,它的作用就是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。
Hibernate的核心:
从上图中,我们可以看出Hibernate六大核心接口,两个主要配置文件,以及他们直接的关系。Hibernate的所有内容都在这了。那我们从上到下简单的认识一下,每个接口进行一句话总结。
1、Configuration接口:负责配置并启动Hibernate
2、SessionFactory接口:负责初始化Hibernate
3、Session接口:负责持久化对象的CRUD操作
4、Transaction接口:负责事务
5、Query接口和Criteria接口:负责执行各种数据库查询
注意:Configuration实例是一个启动期间的对象,一旦SessionFactory创建完成它就被丢弃了。
Hibernate的优/缺点:
优点:
1、更加对象化
以对象化的思维操作数据库,我们只需要操作对象就可以了,开发更加对象化。
2、移植性
因为Hibernate做了持久层的封装,你就不知道数据库,你写的所有的代码都具有可复用性。
3、Hibernate是一个没有侵入性的框架,没有侵入性的框架我们称为轻量级框架。
对比Struts的Action和ActionForm,都需要继承,离不开Struts。Hibernate不需要继承任何类,不需要实现任何接口。这样的对象叫POJO对象。
4、Hibernate代码测试方便。
5、提高效率,提高生产力。
缺点:
1、使用数据库特性的语句,将很难调优
2、对大批量数据更新存在问题
3、系统中存在大量的攻击查询功能
Hibernate的体系结构与开发步骤
Hibernate的体系结构:
Hibernate开发步骤
- 创建持久化类
- 创建对象-关系映射文件
- 创建Hibernate配置文件
- 通过Hibernate API编写访问数据库的代码
第一个Hibernate程序(HelloWorld)
创建Eclipse工程并引入相关的jar包
新建Java工程,并添加如下jar包:
- {hibernate_home}/lib/required/*.jar
- 数据库对应的JDBC驱动(例如mysql-connector-java-5.1.38-bin.jar)
还可以加入日志相关的jar包(不加也可以):
- log4j-1.x.x.jar
- slf4j-log4j12-1.x.x.jar
创建持久化对象:User.java
在cn.itcast.a_helloworld包下创建User类,代码如下:
/*** 实体*/publicclassUser { privateintid; privateStringname; publicintgetId() { returnid; } publicvoidsetId(intid) { this.id=id; } publicStringgetName() { returnname; } publicvoidsetName(Stringname) { this.name=name; } publicStringtoString() { return"[User: id="+id+", name="+name+"]"; } }
创建对象-关系映射文件:User.hbm.xml
首先在MySQL数据库里面创建一个t_user表,建表语句如下:
createdatabasehibernate_20160926defaultcharactersetutf8; usehibernate_20160926; createtablet_user( idintprimarykeyauto_increment, namevarchar(20) );
t_user表创建好之后,我们就要创建相对应的对象-关系映射文件:User.hbm.xml了,注意该映射配置文件与User类要在一起,即同一个包下。
<hibernate-mappingpackage="cn.itcast.a_helloworld"><classname="User"table="t_user"><idname="id"type="int"column="id"><generatorclass="native"/></id><propertyname="name"type="string"column="name"/></class></hibernate-mapping>
关于此映射配置文件中的内容后面会慢慢详解。
创建Hibernate配置文件:hibernate.cfg.xml
我们要在类路径下(即src目录下)创建Hibernate配置文件——hibernate.cfg.xml。
初学者第一次学习Hibernate框架,肯定是不知道如何编写Hibernate配置文件的,但我们可以在{hibernate_home}/project/etc目录下找到开发包给我们提供的Hibernate配置文件,我们只须要拷贝进我们的项目,然后修修改改就可以了。
这样我们的Hibernate配置文件——hibernate.cfg.xml的内容就为:
<hibernate-configuration><session-factoryname="foo"><!-- 1. 配置数据库信息 --><!-- 方言(连接的数据库类型) --><propertyname="dialect">org.hibernate.dialect.MySQLDialect</property><propertyname="connection.url">jdbc:mysql:///hibernate_20160926</property><propertyname="connection.driver_class">com.mysql.jdbc.Driver</property><propertyname="connection.username">root</property><propertyname="connection.password">yezi</property><!-- 2. 其他配置 --><!-- 显示生成的SQL语句 --><propertyname="hibernate.show_sql">true</property><!-- 3. 导入映射文件 --><mappingresource="cn/itcast/a_helloworld/User.hbm.xml"/></session-factory></hibernate-configuration>
关于此配置文件中的内容后面会慢慢详解。
通过Hibernate API编写访问数据库的代码
编程步骤:
- 获取Configuration对象
- 获取SessionFactory对象
- 获取Session,打开事务
- 用面向对象的方式操作数据库
- 关闭事务,关闭Session
由于是Hibernate入门,所以我不会搞得很复杂,就只是简单的向hibernate_20160926数据库中的t_user表中插入一条记录,然后再取出来而已。
我们在cn.itcast.a_helloworld包下创建一个App类,为了方便测试,我使用的是单元测试。
public class App { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xml"); // 读取指定的主配置文件 sessionFactory = cfg.buildSessionFactory(); // 根据配置生成Session工厂 } @Test public void testSave() { User user = new User(); user.setName("张三"); // 保存 Session session = sessionFactory.openSession(); // 打开一个新的Session Transaction tx = session.beginTransaction(); // 开启事务 session.save(user); tx.commit(); // 提交事务 session.close(); // 关闭Session,释放资源(不一定是真正的关闭) } @Test public void testGet() { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user = (User) session.get(User.class, 1); // 获取? System.out.println(user); tx.commit(); session.close(); } }
测试第一个Hibernate程序
编写完第一个Hibernate程序之后,我们就要来测试了,先测试向hibernate_20160926数据库中的t_user表中插入一条记录,发现报如下异常:
org.hibernate.engine.jndi.JndiException: ErrorparsingJNDIname [foo] atorg.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:141) atorg.hibernate.engine.jndi.internal.JndiServiceImpl.bind(JndiServiceImpl.java:157) atorg.hibernate.internal.SessionFactoryRegistry.addSessionFactory(SessionFactoryRegistry.java:103) atorg.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:497) atorg.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859) atorg.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930) atcn.itcast.a_helloworld.App.<clinit>(App.java:16) atsun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeMethod) atsun.reflect.NativeConstructorAccessorImpl.newInstance(UnknownSource) atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(UnknownSource) atjava.lang.reflect.Constructor.newInstance(UnknownSource) atorg.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217) atorg.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266) atorg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) atorg.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263) atorg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) atorg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) atorg.junit.runners.ParentRunner$3.run(ParentRunner.java:290) atorg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) atorg.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) atorg.junit.runners.ParentRunner.access$000(ParentRunner.java:58) atorg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) atorg.junit.runners.ParentRunner.run(ParentRunner.java:363) atorg.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) atorg.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Causedby: javax.naming.NoInitialContextException: Needtospecifyclassnameinenvironmentorsystemproperty, orasanappletparameter, orinanapplicationresourcefile: java.naming.factory.initialatjavax.naming.spi.NamingManager.getInitialContext(UnknownSource) atjavax.naming.InitialContext.getDefaultInitCtx(UnknownSource) atjavax.naming.InitialContext.getURLOrDefaultInitCtx(UnknownSource) atjavax.naming.InitialContext.getNameParser(UnknownSource) atorg.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:135) ... 28more
错误原因:
在hibernate.cfg.xml文件内容的配置
<session-factoryname="foo">... </session-factory>
/
中添加了name属性。
解决办法:
去掉
<session-factoryname="foo">... </session-factory>
中的name属性。
修改之后,测试,通过,大发!