hibernate(api_介绍)

hibernate(api_介绍)
hibernate(api_介绍)

Hibernate API

1 接口类型

1.访问数据库的各种操作的接口

包括Session、Transaction、Query接口。

2.配置Hibernate的接口

Configuration接口。

3.回调接口

使应用程序能够监听Hibernate内部发生的各种事件,并做出相应的回应。

包括Interceptor接口。

4.映射类型接口

Java数据类型和数据库数据类型的映射,如Type、CompositeUserType等接口。

5.扩展接口

功能扩展,如Dialect、IdentifierGenerator等。

Hibernate内部封装了JDBC(Java Database Connector)、JTA(Java Trasaction API)、JNDI(Java Naming and Directory Interface)。我们只要提供JDBC驱动程序就可以通过Hibernate访问任何数据库系统。

1.1 核心接口

1.org.hibernate.cfg.Configuration Interface

配置并根启动Hibernate。通过该接口来指定Hibernate配置文件(hibernate.cfg.xml 或者hibernate.properties)的位置或动态配置Hibernate的属性,接着创建SessionFactory。

2.org.hibernate.SessionFactory Interface

从该接口中获得Session实例,具备以下特点:

a. 多线程安全

b. 重量级,一个数据库对应一个SessionFactory,其创建及销毁消耗资源多。

3.org.hibernate.Session Interface

和我们前面所学的HttpSession没有任何关系。我们在Hibernate应用中使用最广泛的接口。也被称为持久化管理器,提供了相关的数据库操作,比如添、更、删、加、查等基本操作。

特点:

a. 非线程安全。

b. 轻量级,其创建及销毁消耗资源少。每个客户请求对应一个Session。

4.org.hibernate.Transaction Interface

封装了底层事务接口。底层事务接口包括:

a. JDBC API

b. JTA

c. CORBA(Common Object Request Broker Architecture) API

5.org.hibernate.Query 和org.hibernate.Criteria Interface

查询接口。用于向数据库查询对象以及控制执行查询的过程。Query封装了HQL(Hibernate Query Language)查询语句,和SQL很类似,唯一的区别在于HQL是面向对象的。

Criteria完全封装了基于字符串形式的查询语句,更加面向对象,擅长执行动态查询,即参数查询。

1.2 回调接口

org.hibernate.Interceptor Interface

不必由持久化类来实现,可以自定义实现该接口的类,也是响应持久化实例被加载、删除、保存、更新等事件。可以通过该接口实现数据更改日志。

1.3 映射接口

Type接口,表示Hibernate映射类型,是域对象映射为数据库的关系数据。提供了各种实现类:

org.hibernate.type.PrimitiveType Class:映射java基本数据类型,自然就有对应的8个子类。

org.hibernate.type.DateType Class:映射java日期类型

org.hibernate.type.BinaryType Class:映射Byte[]类型

当然,也可以通过实现https://www.360docs.net/doc/e64679545.html,erType和https://www.360docs.net/doc/e64679545.html,positeUserType接口来自定义数据映射类型。

1.4 可扩展接口

1.org.hibernate.dialect.Dialect abstract_class

Hibernate对于每种数据库都定义了独有的方言,比如Oracle、MSSQL、Sybase等数据库系统都有特定的方言。Hibernate有不同实现了Dialect的类,每个类对应特定数据库,如OracleDialect等。可以自定义方言。

2.IdentifierGenerator Interface

定制主键的生成策略。后面详述。

3.Cache Interface

定制缓存机制。

4.ConnectionProvider Interface

定制JDBC连接管理。

。。。。。。。。。。。。。。。

Hibernate的简单应用

2.1 使用Hibernate技术步骤一:Create Hibernate Configuration File(...cfg.xml 或者.properties)

配置文件应存储和数据库连接的相关信息,如连接驱动器类或者数据源名称等。

例子:(XML文件) 扩展名为.cfg.xml

hibernate.cfg.xml

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"https://www.360docs.net/doc/e64679545.html,/hibernate-configuration-3.0.dtd">

jdbc:microsoft:sqlserver://localhost:1433;databasename=usercheck

com.microsoft.jdbc.sqlserver.SQLServerDriver

sa

Properties文件:扩展名为.properties

hibernate.properties

注意:如果在Web程序中,应放在src目录下

2.2 步骤二:Create persistent class

符合JavaBean规范。

如果是boolean属性,则可以用get作为getter方法前缀之外,也可以用is作为前缀。

Hibernate要求持久化类必须提供一个无参数的构造方法,因为它会运用java的反射机制来构造持久化类的实例。

2.3 步骤三:Create ORM File(...hbm.xml)

对象和关系(表)数据之间的映射。XML文件。

SQL语句的生成就是依据该文件生成的。注意:该文件应该和其所对应的持久化类放在同一目录下,即同一包中。一般是一个持久化类对应一个映射文件。当然,也可以一个映射文件对应多个持久化类。扩展名为.hbm.xml。

简单例子:Product.hbm.xml

<!-- 指定类和表的映射 -- >

<!-- 持久化类的OID和表主键的映射,必须且只能出现一次 -- >

<!-- 指定OID的生成器 -->

<!-- 类属性和表字段的映射 -->

2.4 步骤四:通过Hibernate API访问数据库

大部分类和接口均来自net.sf.hibernate包。

必须使用到Configuration类、Session接口、SessionFactory接口,还经常用到Transaction 接口、Query接口、FlushMode接口等等。

Session的各种方法:

1.save()

2.update()

3.delete()

4.load()

5.saveOrUpdate()

6.get()

对象与关系的映射

3.1 持久化类的属性及其访问方法

当Session执行save()、update()、saveOrUpdate()方法时,会调用持久化类的各个属性的getXXX()方法来获取属性值。而执行get()、load()、find()方法时则调用持久化类属性的setXXX()方法来设置属性值。

注意:在java程序里,我们都知道访问级别为私有的方法是不能在类外被访问的,也可以理解为持久化类的私有类型的setXXX()、getXXX()方法不能被其它java程序访问,而对于Hibernate来说则没有这个限制,不管是什么访问级别的setXXX()、getXXX()方法都可以访问。

3.1.1 java基本数据类型和包装类型

上面的附录我们可以得知,对应于java中的每个基本数据类型及对应包装类都有一个特定的Hibernate数据类型与之对应。比如int对应java中的int和Integer。

一般我们都会将持久化类中的属性定义为基本数据类型,但是在实际应用中可能会有这样的问题,比如int类型在java中的默认值为0,我们在给学生表插入数据时,有这样一个字段score(分数),如果在将持久化类对象保存到数据库中时没有给分数属性赋值,那么分数的缺省值就是0,也就是说插入到学生表中的这条记录中,该学生的分数为零,而我们的初衷并不是这样,我们之所以没给分数属性赋值是因为该学生的分数还是未知的,而不应该是0分。

从上面的例子可以看出,基本类型的缺点在于无法表达null值(而数据库中所有的数据类型的默认值为null)。如果我们将分数属性换成包装类Integer,那分数值即可为null(未知),也可以为0。

另外,hibernat对包装类提供了良好的支持。许多方法都以包装类作为参数。

一般,推荐大家对于持久化类的OID使用包装类型,因为hibernate会根据OID是否为null来判断持久化类对象的状态(后面章节会详述对象状态)。

3.1.2 派生属性

现有products表,在hibernate中对应有一持久化类Product,通过映射文件已将两者联系起来,产品表包含有两个字段,分别为sales_quantity、price,现客户想得到某一产品的总销售额。我们可以通过两个途径解决,一种就是将得到的类Product的属性sales_quantity、price进行相乘得到总销售额。另一种方法就是在类Product中增加一个属性total_price,接着修改映射文件,添加以下语句:

大家可以通过以上语句发现,没有column属性了,total_price在表products中没有对应字段,因此我们不能通过column属性将其映射到表中的字段,total_price实际上对应的是sales_quantity和price两字段的乘积,通过formula属性来定义。这样,我们可以直接通过持久化类Product的total_price属性的get方法得到产品销售总额。total_price属性我们就称之为派生属性。

3.1.3 控制属性的插入和更新

注意:Hibernate在初始化阶段就会依据映射文件为所有持久化类预定义以下语句:1.Update语句

比如:update products set pname=?,desc=?,price=?...where pid=?

2.Inset语句

比如:insert into products(pname,desc,price...) values(.. ..) 3.Delete语句

比如:delete from products where pid = ?

4.Select语句

比如:select pname,desc,price... from products where pid = ?

(HQL和QBC查询对应的select语句是在执行时动态生成)

以上预定义语句在当执行Session的save()、delete()、update()、load()时被执行,同时将具体的参数值绑定到预定义语句中。

因此,我们可以理解,当我们执行以上方法时,Hibernate会自动将预定义好的语句提交到rdbms,进行相应的数据操作。

比如,调用update()方法时,就会对表的所有字段更新记录,这样我们就不必写sql 语句。可在实际中可能会有这样的情况,在资产信息表中,一般客户要求资产的编号不能更改,而按照预定义语句,我们在调用Session的save()方法时能对所有字段更新,从而违背了业务逻辑。当然,我们可以通过将资产编号属性的setXXX()方法设为私有,但这样会导致其它操作也不能作用于该属性。

在Hibernate中,可以通过元素的特定属性来控制应更新或者插入的字段,例子:

column=”serial_num” >

上面语句代表在update和insert语句中不会包含serial_num字段,也就是不能对该字段进行更新和添加。

1.

.. .. ...

表示class内的所有元素的update属性为false,也就是整个持久化类实例不能被更新。

2.

当保存一个对象时,动态生成insert语句。只有该属性的值为非空时,才会将该属性对应得字段包含在insert语句中。

3.

同上。只有该属性值变化时,才会更新对应字段。

4.

.. . ...

等价于所有property元素的属性dynamic_insert为true。

5.

.. . ...

等价于所有property元素的属性dynamic_update为true。

注意:动态生成语句的系统开销很小,不影响性能。如果涉及的表包含多个字段,那我们应实现动态语句的生成。也就是说,我们可以只对需要插入或者更新的字段进行操作,这样可以节省SQL语句执行时间。

3.2 设置类的包名

通常情况下,我们在设置元素时,name属性必须提供完整类名,也就是要包括类所在的完整包名。

之前我们所做的是一个映射文件包含一个类的映射,在复杂的项目中,为了避免映射文件过多,我们也可以在一个映射文件中包含多个类的映射。比如:

….

….

….

以上文件中映射了多个表和类,但是我们发现,每写一个class元素时,我们都要在name 中写上长串相同的包路径,这是一个繁琐而且容易出错的过程,因此,Hibernate提供了一个特有的属性package,用法如下:

….

….

….

该文件和上面的文件等同。

持久对象标识符(OID)

4.1 RDBMS中的主键定义类型

5.1.1 自动增长列

MySQL中主键类型为auto_increment,则该主键会自动增长赋值。

MS SQL Server中主键类型为identity,则该主键会自动增长赋值。

5.1.2 序列

Oracle中,可以为每张表的主键创建一个单独的序列。

4.2 Hibernate通过OID来区分对象

OID(Object ID)是RDBMS中的主键在java持久对象模型中的等价物,即主键在java中的对应标识符。

看以下例子:

1.Trancation t = session.beginTransaction();

2.Product p1 = session.load(Product.class,new Integer(1));

3.Product p2 = session.load(Product.class,new Integer(1));

4.Product p3 = session.load(Product.class,new Integer(2));

5.System.out.println(p1 == p2);

6.https://www.360docs.net/doc/e64679545.html,mit();

下面我们来分析以上代码,2,3,4行代码中,hibernate三次调用了load方法,分别加载了OID为1或3的Product对象,语句2从数据库中对应的Products表中获取pid为1的记录,接着创建相应Product实例,保存到Session缓存中,最后将该实例的引用赋给变量p1。语句3执行时,hibernate直接把缓存中OID为1 的Product对象的引用赋给p2(注意:并没有重新创建一个新的Product对象)。语句4执行时,发现缓存没有对应的对象,因此会重新到数据库中获取对应记录,以后步骤和语句1 雷同。

因此,我们可以得知,语句5输出的值为true。

OID是整数类型,和表的代理主键对应,Hibernate允许OID使用以下整数类型:

1.short or Short 2byte

2.Int or Integer 4byte

3.long or Long 8byte

注意:一般我们将OID的set方法设为私有的(除了使用自然主键),以防止在应用程序中攥改OID。因为OID一般都是由Hibernate或者数据库自动生成(代理主键的特性),不建议我们手动去生成id。

元素专门用来设定OID的生成器(类)。其中class属性值定义了各个生成器的缩写别名。

4.2.1 Hibernate的内置标识生成器

实际上,Hibernate的内置标识生成器就是指的生成各种OID的特定类,全部在org.hibernate.id包中。列出如下:

1.IdentityGenerator --Class

缩写别名:identity

适用于代理主键,由底层数据库来生成OID,注意:要求底层数据库支持自动增长

类型(MySql、SQLServer、Sybase),且对应表的主键应为自动增长列。

当我们插入数据时,Hibernate生成的sql插入语句中不会包含对应的主键字段,因

为该字段的值是由数据库生成的。

2.IncrementGenerator --Class

缩写别名:increment

适用于代理主键,由hibernate自动生成OID。实现机制:hibernate先到数据库中寻找对应表主键的最大值然后在该值上加一,从而生成OID。

3.SequenceGenerator ---Class

缩写别名:sequence

适用于代理主键,由底层数据库提供的序列来生成OID,注意:要求底层数据库支持序列(Oracle、DB2)。

sequence_name

4.

缩写别名:native

适用于代理主键,由底层数据库自动生成OID,实现机制:根据对应表的主键的类型,比如identity、sequence,自动按照这些类型生成OID,也可以理解为native支持identity、increment、hilo和sequence这几种方法生成OID。适合于跨数据库平台开发。

相关主题
相关文档
最新文档