Hibernate学习总结
学习Hibernate好几天的,通过下面三个问题来总结一下:
第一个问题:HIbernate是什么?
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
重要的就是他对JDBC进行了轻量级的封装,在学习JDBC的时候,我们要每一个操作都要做连接数据库关闭数据库;虽然老师给我们做了一定的封装,但也要求我们对数据库和SQL语句和熟练才能操作,而且我们在编写代码的同时必须打开我们的数据库,查看我们建立的表和列,要和我们的对象一一对应,如果你的表名起的很随意,列名也很随意,好吧,你就慢慢对吧。但是如果我们使用Hibernate来操作的,我们只需要在配置文件里将对象和表,属性和普通列,id和主键等一一对应起来即可,只要我们的配置文件正确,无误,那么什么表啊列的啊都是浮云了,一切都和你无关了,你的眼里就只有类,对象,和属性就万事大吉了,对于数据库和SQL语句学的很虚的同学来说,简直就是福音啊;当然Hibernate不可能这么肤浅,还有很多更有用的功能等待我们去学习。
第二个问题 Hibernate有什么用?
Hibernate的作用第一个问题已经说了啊,总结一下吧,
1. 不需要编写SQL语句,而且允许采用OO方式访问数据库
2 .它支持各种关系数据库,从一对一到多对多的各种复杂关系。
3. Hibernate是以操作对象的方式,实现对数据库的操作,减少了数据库操作的代码。还设计了很多调优策略。而他有时基于JDBC的一种封装,所以执行效率比JDBC稍差
4, JDBC访问的大量的checked异常也被包装成Hibernate的Runtime异常,从而不再要求程序员必须处理所有异常;
第三个问题 Hibernate怎么用?
怎么用应该是学习Hibernate的核心了,一切都为了使用,前面都是废话,会用才是关键;
Hibernate配置:
1. 配置eclipse的link文件:
Feature plugins -->eclipse -->hibernate hibernate.link --->links --->eclipse_JEE
hibernate.link ----->Path=D:\\eclipse3.6EE\\links\\Hibernate\\clipse
2. 导入Hibernate所需的jar包
添加的jar包:hibernate3.jar lib—required,jpa----jar;
3. 创建hibernate配置文件:hibernate.cfg.xml
<?xmlversion='1.0'encoding='utf-8'?>
<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 1.数据库连接 -->
<!--数据库连接URL -->
<propertyname="connection.url">
jdbc:oracle:thin:@localhost:1521:XE</property>
<!--数据库用户名 -->
<propertyname="connection.username">mytest</property>
<!--数据库密码 -->
<propertyname="connection.password">123456</property>
<!--数据库JDBC驱动类名 -->
<propertyname="connection.driver_class">
oracle.jdbc.driver.OracleDriver</property>
<!-- 2.Hibernate配置 -->
<!--数据库方言不同数据库使用不同的方言-->
<propertyname="dialect">
org.hibernate.dialect.Oracle10gDialect</property>
<!-- ddl语句自动建表 -->
<propertyname="hbm2ddl.auto">none</property>
<!--是否输出Hibernate生成的SQL语句,开发阶段一般需要开启 -->
<propertyname="show_SQL">true</property>
<!--是否对输出SQL进行格式化 -->
<propertyname="format_SQL">true</property>
<!-- 3.连接池配置 -->
<!--连接池,使用第三方jar包,hibernate自带的功能较差 -->
<propertyname="hibernate.connection.provider_class">
org.hibernate.service.jdbc.connections
.internal.C3P0ConnectionProvider
</property>
<!--这是C3P0随时准备好的最少的JDBC连接数量 -->
<propertyname="hibernate.c3p0.min_size">5</property>
<!--连接池中JDBC连接的最大数量 -->
<propertyname="hibernate.c3p0.max_size">20</property>
<!--超时周期,在它之后,闲置连接将从池中移除 -->
<propertyname="hibernate.c3p0.timeout">300</property>
<!--最多高速缓存100个预编译语句,该属性是使Hibernate获得较好性能的要素。-->
<propertyname="hibernate.c3p0.max_statements">100</property>
<!--连接被自动验证前,以秒为单位的闲置时间 -->
<propertyname="hibernate.c3p0.idle_test_period">3000</property>
<!-- 4.实体类映射文件-->
<!--注册ORM实体类映射文件-->
<mappingresource="entity/Type.hbm.xml"/>
[……]
</session-factory>
</hibernate-configuration>
4. 创建实例的配置文件:XXX.hbm.xml
<?xmlversion="1.0"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!—第一种: 自动根据映射生成对应的数据表 -->
<hibernate-mappingpackage="wngn.zzia.entiry">
<classname="User"table="user">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="username"/>
<propertyname="password"/>
<propertyname="nickname"/>
<propertyname="born"type="timestamp"/>
</class>
</hibernate-mapping>
<hibernate-mapping package="wngn.book.entity">
<!-- 第二种: 根据映射字段对应数据表 -->
<class name="Type" table="lm_type">
<!-- 属性和主键 -->
<id name="id" column="type_id">
<!-- 主键生成策略 -->
<generator class="sequence">
<!--sequence对象的名字 -->
<param name="sequence">lm_type_seq</param>
</generator>
</id>
<property name="name" column="type_name"/>
<property name="desc" column="type_desc"/>
<set name="books">
<key column="type_id"></key>
<one-to-many class="wngn.book.entity.Book" />
</set>
</class>
</hibernate-mapping>
5. 编写代码,测试结果
1. 开发持久化类,有POJO加映射文件组成
2. 获取Configuration
3. 获取SessionFactory
4. 获取Session,打来事务
5. 用面向对象方式操作数据库
6. 关闭事务,关闭session
Hibernate的三种状态:
瞬时状态:
如果PO实例从未与session关联过,该PO处于瞬时状态
持久化状态:
如果PO实例与session关联起来,且该实例对应到数据库记录,该实例处于持久化状态;
托管状态:
如果PO实例曾经与session关联过,但因为session的关闭等原因,PO实例脱离了session的管理,这种状态称为托管
对PO的操作必须在session的管理下才能同步到数据库;Session必须有SessionFactory工厂产生;SessionFactory是数据库编译后的内存镜像,通常一个应用对应一个SessionFactory对象,SessionFactory由Configuration对象生成,Configuration对象负责加载Hibernate配置文件。
Hibernate的主要接口:
SessionFactory:
(hibernate关键对象)他是单个数据库映射关系经过编译后的内存镜像,线程安全,他是生成Session的工厂,依赖于ConnectionProvoder;
Session:
(hibernate关键对象)他是应用程序与持久存储层之间交互操作的一个单线程对象,所有持久化对象必须在Session对象的管理下才可以进行持久化操作;此对象的生存期很短,他底层封装了JDBC连接,他也是Transaction的工厂;
ConnectionProvoder:
连接提供者,他是生成JDBC连接的工厂,它通过抽象将应用程序与底层的DateSource或DriverManager隔离开,
TransactionFactory:
事务工厂,生成Transaction的工厂,它负责对底层的事务实现封装,将底层的事务抽象成Hibernate事务;
Configuration
Configuration实例代表了应用程序到SQL数据库的映射配置;提供了一个buildSessionFactory方法,该方法产生一个不可变的SessionFactory对象;
创建Configuration对象:
使用hibernate.properties作为配置文件
/*多次调用addResource方法,添加映射文件*/
Configuration cfg =new Configuration ()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");
/*多次调用addResource方法,直接添加持久化类*/
Configuration cfg =new Configuration ()
.addResource("lee.Item.Class")
.addResource("lee.Bid.Class");
使用hibernate.cfg.xml作为配置文件
/*configure方法会负责加载hibernate.cfg.xml文件*/
Configurationcfg =new Configuration ().configure();
不使用配置文件创建Configuration 实例;通过代码设置hibernate配置,极其繁琐;
Hibernate的实体映射关系
多对一: ----> private Typetype;
<many-to-onename="type"class="entity.Type">
<columnname="type_id"></column>
</many-to-one>
1、name为属性名,class为“one”端类名
2、外键列列名
一对多:---->private Set<Book>books;
<set name="books">
<keycolumn="type_id"></key>
<one-to-manyclass="entity.Book"/>
</set>
1、set集合节点适用于配置一对多关联关系, name属性指定one的一端对应属性名。
2、外键列列名。
3、class属性指定many端的全限定类名。
一对一
book:
<many-to-onename=“type"class=“**"column=“type_id" unique="true"/>
type:
<one-to-onename=“book"class=“**"property-ref=“type"/>
联合主键
<composite-id>
<!--同时表达这是外键-->
<key-many-to-onename=“**”column=“***"class=“***"> </key-many-to-one>
<key-many-to-onename=“**”column=“**"class=“**">
</key-many-to-one>
</composite-id>
Hibernate 中id的自动生成策略
<id name="id">
<!-- 表示不会自动生成,而是需要由用户来指定 -->
<!-- <generator class="assigned"/> -->
<!-- 会自动生成一个字符串,此时组件必须为String类型 -->
<generator class="uuid"/>
</id>
<id name="id">
<!-- 会自动生成一个整数,此时组件必须为int类型 -->
<generator class="native"/>
</id>
Assigned:第一次添加数据时id默认为0,第二次添加数据会报错,
Uuid:永远不会重复;
native 需要查询数据库,找到最大的id在插入,插入时效率低,优点是查询时方便,效率高
Uuid 系统自动生成,不需要查询数据库就能插入,比native效率高
最佳实践:项目当中查询用的最多,所以一般都用native。