Hibernate技术文档
hibernate数据持久化组件
对象持久化,把数据保存在永久的存储介质中(数据库)
OR/M(object relationmapping)对象关系映照。
POJO类,就是标准的Java Bean。
Hibernate就是1个可以自动的根据xml完成对象关系映照,并持久化到数据库的开源组件。
Hibernate的底层也是有JDBC实现的。
hibernate是通过xml文件的配置,对数据库的底层的方言,和数据库连接所需的信息,和连接数据库的驱动。hibernate的系统配置文件的名字1般叫做hibernate.cfg.xml,
1般是映照类名加.hbm.xml。1般将映照类的xml文件和实体类放在1起。
hibernate.cfg.xml中会设置数据库的连接信息,和援用的其他文件的文件名,和1些其他的摄制。这个文件1般放在项目的根目录下。
在hibernate.cfg.xml的写法
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/HibernateConfiguration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration⑶.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="show_sql">true</property><!--显示sql语句-->
<propertyname="format_sql">true</property><!--使显示的sql语句格式化-->
<property name="dialect">....</property><!--使用的数据库方言信息-->
<propertyname="connection.driver_class">....</property>
<!--使用的数据库的驱动-->
<propertyname="connection.url">....</property><!--连接数据库使用的url-->
<propertyname="connection.username">...</property>
<!--连接数据库的用户名-->
<propertyname="connection.password">...</property>
<!--连接数据库的密码-->
<mappingresource="xxx/xxxx/Xxxxxx.hbm.xml"/>
<!--引入的映照对象的xml文件的全路径及文件名-->
</session-factory>
</hibernate-configuration>
hibernate的映照类的XXXX.hbm.xml的写法
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/HibernateMapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping⑶.0.dtd">
<hibernate-mapping package="XXX.XXX.XXX"><!--映照类所在的包-->
<classname="Xxxxxx" table="Xxxxx"><!--将类和数据库的表联系起来-->
<idname="studentId" column="studentId"><!--主键生成策略-->
<generatorclass="assigned"/>
<!--指定主键生成策略为用户指定-->
</id>
<propertyname="XXX" column="XXXX" type="string"/>
<!--类中的书性和字段之间建立联系-->
<property name="homeAddress"column="homeAddress"/>
<propertyname="schoolAddress" column="schoolAddress"/>
<propertyname="brithday" column="brithday"type="data"/>
<!--在hibernate中其他类型可以自动辨认只有Data类型必须指名-->
</class>
</hibernate-mapping>
使用hibernate编程步骤
1,配置环境,加载hibernate的jar文件,和连接数据库连接使用的jar文件,并配置CLASSPATH环境变量。
2,写hibernate所需的配置文件,hibernate.cfg.xml ,Xxxxx.hbm.xml
3,写POJO类
4,调用hibernate API。
1)使用Configuration对象的buildSessionFactory()方法创建SessionFactory对象
2)使用SessionFactory对象openSession()方法创建Session对象。
3)使用Session的相应方法来操作数据库,将对象信息持久化到数据库。
hibernate的配置文件hibernate.cfg.xml用于配置数据库的连接的信息,和需要持久化的对象的xml映照文件的位置
在hibernate.cfg.xml中使用<mappingresource="xml/Student.hbm.xml">这类方式来指名要持久化对象的映照文件。
Configuration是用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并产生SessionFactory对象。
SessionFactory是和1个数据库逐一对应的,他只能对应1个hibernate.cfg.xml文件,1个hibernate.cfg.xml中只能配置1个数据库的连接信息。
POJO(普通的java类)
持久化对象和临时对象,持久化对象,即对象的信息在数据库中存在,在内存中也有。临时对象也就是新对象,没有同步到数据库。
Session,持久化管理器。
Hibernate的核心接口
1.Configuration,用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并创建SessionFactory对象。
2.SessionFactory,用于创建Session对象。
3.Session,持久化管理器,对象级数据库操作
4.Query,对对象作持久化操作或查询操作
5.Transaction ,用于管理操作事务。
hibernate.cfg.xml中的标签
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/HibernateConfiguration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration⑶.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="show_sql">true</property><!--显示sql语句-->
<propertyname="format_sql">true</property><!--使显示的sql语句格式化-->
<propertyname="dialect">....</property><!--使用的数据库方言信息-->
<propertyname="connection.driver_class">....</property>
<!--使用的数据库的驱动-->
<propertyname="connection.url">....</property><!--连接数据库使用的url-->
<propertyname="connection.username">...</property>
<!--连接数据库的用户名-->
<propertyname="connection.password">...</property>
<!--连接数据库的密码-->
<mappingresource="xxx/xxxx/Xxxxxx.hbm.xml"/>
<!--引入的映照对象的xml文件的全路径及文件名-->
</session-factory>
</hibernate-configuration>
对象映照文件
<hibernate-mapping package="XXX.XXX.XXX"auto-import="false"><!--映照类所在的包-->
<classname="Xxxxxx" table="Xxxxx"><!--将类和数据库的表联系起来-->
<idname="studentId" column="studentId"><!--主键生成策略-->
<generatorclass="assigned"/>
<!--指定主键生成策略为用户指定-->
</id>
<propertyname="XXX" column="XXXX" type="string"/>
<!--类中的书性和字段之间建立联系-->
<propertyname="homeAddress" column="homeAddress"/>
<propertyname="schoolAddress" column="schoolAddress"/>
<propertyname="brithday" column="brithday"type="data"/>
<!--在hibernate中其他类型可以自动辨认只有Data类型必须指名-->
</class>
</hibernate-mapping>
id生成方式
1,序列sequence 只适用于Oracle
<id name="id" column="id">
<generatorclass="sequence">
<paramname="sequence">person_seq</param><!--指定sequence名-->
</generator>
</id>
2,自增列,适用于SQLServer
<id name="id" column="id">
<generatorclass="identity"/>
</id>
3,取最大值加1
<id name="id" column="id"type="integer">
<generatorclass="increment"/>
</id>
4,根据底层数据库指定生成方法
<id name="id"column="id">
<generatorclass="native"/>
</id>
针对Oracle数据库的生成方式还是sequence,只不过需要1个特定名字的sequence,"hibernate_sequence"。
5,高低位算法
<id name="id" column="id">
<generatorclass="hilo">
<paramname="table">high_value</param>
<!--设置高位值取值的表-->
<paramname="column">next_value</param>
<!--设置高位值取值的字段-->
<paramname="max_lo">50</param>
<!--指定低位最大值,当取道最大值是会再取1个高位值再运算-->
</generator>
</id>
类关联关系映照
1对1关系实现
建表策略
1,同享主键,也就是1方援用另外一方的主键,作为本身的主键,也是外键。
2,外键援用,也就是1方援用另外一方的主键,作为外键,并且对援用的外键加唯1束缚。
1对多
建表策略,多方援用1方的主键当作外键
持久化对象,即就是在数据库中存有其相对应数据的对象,并且在内存中也有这个对象,这个对象在Session的管理范围内,也就是调用过save()方法同步到数据库的对象。
临时对象,即在内存中刚刚创建的对象,还没有同步到数据库,或是数据库中信息被删除的对象也是临时状态。
游离对象,也就是在数据库中有和该对象向对应的纪录,并且在内存中的也存在该对象,但是不在Session的管理范围以内,也就是在Session关闭以后,就成了游离对象,就不会在将其改变同步到数据库中,如果要使还想令其成为持久化对象就要在把它纳入Session管理中,也就是掉用Session中的update()方法就能够了。
及物的持久化,也就是说针对这个对象的属性进行持久化操作,也就是通过级联进行设置。
以下是1对多中1端set标签的设置
<set name="st" inverse="true"cascade="delete" batch-size="3">
<keycolumn="cid"/>
<one-to-manyclass="Student"/>
</set>
inverse="true"就是在设置如果在内存中的修改或添加了这个集合中的某1个或某几个对象他不会将全部集合的信息同步到数据库,而是只将集合中被修改的对象重新同步到数据库。
cascade属性是设置级联操作的也就是在操作1真个数据如果影响到多端数据时会进行级联操作,
cascade="none",cascade="save-update",cascade="delete",cascade="all"cascade="persist"
cascade="delete-orphan",cascade属性的值经常使用的设置为以上5项:
none就是不使用级联操作,默许级联是none。
save-update也就是只有对象保存操作(持久化操作)或是持久化对象的更新操作,才会级联操作关联对象(子对象)。
persist就只是将级联对象也持久化到数据库。
delete对持久化对象的删除操作时会进行级联操作关联对象(子对象)。
all对持久化对象的所有操作都会级联操作关联对象(子对象)。
all-delete-orphan,在多端进行删除操作时,会再多端表中留下null空纪录,设置了级联操作为delete之会将表中表示关联的外键id置成null,不会将这条纪录也删除掉,而把级联设置成delete-orphan就不会留有空纪录,而是级联的把相干纪录删除掉。
batch-size这个属性只能够写在set标签中,这个属性带表批量加载,也就是在加载1真个集合属性时会1次加载指定的数量的对象,而不是默许的1个1个的加载,会提高效力,批量加载只能用于延迟加载和立即加载策略,也就是(lazy="true"或lazy="false")。
lazy="true"延迟加载,所谓的延迟加载,就是对1真个集合属性的加载策略,就是在不使用到集合中的对象的数据就不会真实的加载集合中的对象数据,而是家在1个代理对象就相当于的1个空的容器。这也就是会出现LazyInitializationException异常,也就是没有初始化这个代理的集合对象,在事前查询到了集合中的对象就会初始化这个对象,如果Session没有关闭就会在查询加载集合中的对象信息,如果提早关闭了Session,当使用集合中的对象信息时就会有这个异常。
fetch="join",这就是使用了预先抓取策略,也就是针对关联的对象的加载策略,在使用到关联对象的信息时会再发送sql语句,如果不使用fetch="join",就会不使用表连接而是先查出1真个关联id再1条1条的发送sql语句查询到关联对象信息,使用了fetch="join"就会使用表连接将关联对象信息直接查寻出来的。fetch="lazy"这个是默许的设置。
注意:
在使用fetch="join"要辨别开他和外连接的区分,他不会疏忽配置文件中的加载策略,而使用了外连接就会疏忽配置文件中使用了外连接的1真个所有加载策略,而替之为立即加载。
例:班级 tream,身份证 Certigicate 学生 student
身份证和学生是1对1关系,班级和学生是1对多的关系。学生对身份证的加载策略是预先抓取,学生对班级是预先抓取,但是班级对学生是延迟加载。
现在使用了外连接
Query q=session.createQuery("from Student as s left joins.team");
as 的语法是取别名的语法。
也就是使用了外连接的来查寻班级,这样就会疏忽,学生对象对其所有属性除使用外连接查寻的属性,而其余都会使用立即加载。
<property name="" column="" type=""not-null="true">,这样也就会使这个属性不能够为空值
查询对象,可使用get()和load()方法,不过条件是必须知道该对象持久化时的唯1标识,也就是id,和这个对象的类对象。
hibernate的HQL中的select和update语法
select 别名 from 类全名 别名 where 别名.类属性=:变量名
如果要查寻全部可以简写为from 类全名
update 类全名 set 属性名=:变量名 where 属性名=:变量名
注意以上这些语句要在createQuery("...")中。
多对多的映照实现
1般多对多关联会拆分成两个1对多的关系来实现多对多关系,也能够通过hibernate提供的解决方案来实现。其实hibernate的实现方式是通过中间表间接的实现了多对多关系,实际上也是将多对多拆分成两个双向的1对多关系。
多对多关系XML文件的配置
<hibernate-mapping>
<class name="Course" table="course">
<set name="clazz"table="class_course" inverse="true"><!--设置中间表的表名-->
<keycolumn="courseid">
<many-to-manycolumn="classid" class="Clazz"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="Clazz" table="class">
<setname="course" table="class_course"cascade="save-update">
<keycolumn="classid"/>
<many-to-many column="courseid"class="Course"/>
</set>
</class>
</hibernate-mapping>
类继承关系映照
建表策略
1.所有类建1个表,只为具体类建表,每一个类建1个表。
2.只为具体类建表,使用于不使用多态的情况下,具体类之间没有继承关系时适用
3.需要针对每一个类写映照配置文件,就和普通的单表映照的xml文件相同。
4.也能够使用1个xml文件来进行映照,可以通过写union-subclass标签来表现其关系
5.这里不能使用id生成策略中的native,而是要指定特定的生成策略。
例:
<union-subclass name="notpad"table="tpcc_notpad">
<property name="wight" column="wight"type="integer"/>
</union-subclass>
<union-subclass name="desktop"table="tpcc_desktop">
<propertyname="LCD" column="isLCD" type="yes_no"/>
</union-subclass>
每一个类建1个表,可以有效减少数据的冗余,减少字段,查询效力不很高。
正对每一个类建1个表,只要写1个配置文件来进行类的映照便可
映照文件中的子类可使用join-subclass标签来表示,并且援用父类的主键作为同享主键,就是不需要指定id生成策略
例:
<hibernate-mapping package="alan.hbn.rel.inherit"auto-import="false">
<classname="Computer" table="tph_computer">
<idname="comid" column="comid" type="long"unsaved-value="0">
<generatorclass="identity"/>
</id>
<propertyname="price" column="price" type="integer"/>
<joined-subclassname="notpad" table="tpc_notpad">
<key column="comid" />
<property name="wight"column="wight" type="integer"/>
</joined-subclass>
<joined-subclassname="Guest" table="tpc_guest">
<key column="comid"/>
<property name="LCD"column="isLCD" type="yes_no"/>
</joined-subclass>
</class>
</hibernate-mapping>
所有类只建1个表,查寻效力比较高,但是会产生很多空间浪费,当子类中的非空束缚,就不大适用了,这是对子类可使用subclass标签表示。
<hibernate-mapping package="alan.hbn.rel.inherit"auto-import="false">
<classname="Computer" table="tph_computer">
<idname="id" column="id" type="long"unsaved-value="0">
<generatorclass="identity"/>
</id>
<discriminatorcolumn="computer_type" type="integer"/>
<propertyname="price" column="price" type="integer"/>
<subclassname="Administrator" discriminator-value="ad">
<propertyname="wight" column="wight" type="integer"/>
</subclass>
<subclass name="Guest"discriminator-value="gu">
<property name="LCD"column="isLCD" type="yes_no"/>
</subclass>
</class>
</hibernate-mapping>
不斟酌多态时,最好是用只针对具体类建表,而斟酌多态时尽可能使用所有类建1个表,只有当子类中的属性过量是才斟酌每一个类建1个表的策略。
Hibernate控制的事务
事务保证原子操作的不可分,也就是操作的同时成功或同时失败。
Transactiontran=session.beginTranaction();
tran.commit();
tran.rollback();
以上是事务对象的方法,来实现对事务的支持。
hibernate的事务隔离级别
hibernate的事务隔离级别和JDBC中大致相同。
设置时要在hibernate.cfg.xml配置
<propertyname="hibernate.connection.isolation">4</property>
1,读未提交的数据(Read uncommitted isolation)
2,读已提交的数据(Read committed isolation)
4,可重复读级别(Repeatable read isolation)
8,可串行化级别(Serializable isolation)
hibernate的锁(悲观锁,乐观锁)
悲观锁是由数据库本身所实现的,会对数据库中的数据进行锁定,也就是锁行。
LockMode.UPGRADE,修改锁,在get()方法中加上这个设置作为第3个参数。
LockMode.NONE 无锁机制
LockMode.READ 读取锁
LockMode.WRITE 写入锁,不能在程序中直接使用
还可使用Session.lock()Query.setLockMode() Criteria.setLockMode()方法来设置锁
乐观锁,也就是通过对记录加上某些信息来解决并发访问的问题。
版本检查
要在其表中多加上1列表示版本信息,会在读取时读到这个版本号,并在修改以后更新这个版本号,并且只有版本号相同才会予以更新,如果版本号低,就会抛出例外。
<versionname="version" column="version" type="integer"/>
时间戳
使用时间戳,是通过最后修改时间来判断是不是来做更新操作,也就是只有在最后更新时间以后才会做更新。
<timestampname="updateTime" column="updatetime"/>
hibernate组件映照
组件不会生成唯1标识,但是也需要对应实体类。
hibernate中可以把1个类的对象当作1个属性组件来使用,并且在使用时会自动创建,所以同1组件对象是不会被两次援用的。
例:
<hibernate-mappingpackage="alan.hbn.rel.inherit" auto-import="false">
<class name="Guest"table="guest">
<id name="id"column="id" type="long" unsaved-value="0">
<generatorclass="native"/>
</id>
<propertyname="userName" column="userName"type="string"/>
<propertyname="password" column="pwd" type="string"/>
<propertyname="birthday" column="birthday"type="date"/>
<componentname="homeAddress" class="Address">
<propertyname="street" column="street"type="string"/> <propertyname="zipcode" column="zipcode" type="string"/> </component>
</class
</hibernate-mapping>
hibernate的HQL(hibernate Query Language)
HQL是hibernate的查询语言,他可以支持面向对象的查询。使用HQL语句,只能通过session.createQuery("...")。
使用hibernate分页显示,使用Query对象的setFirstResult(int firstResult)(firstResult从零开始)方法和setMaxResults(int maxResults) 方法。他会根据不同的底层数据库来显示指定数量的记录。