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
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,接着修改映射文件,添加以下语句:
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内的所有 2. 当保存一个对象时,动态生成insert语句。只有该属性的值为非空时,才会将该属性对应得字段包含在insert语句中。 3. 同上。只有该属性值变化时,才会更新对应字段。 4. .. . ... 等价于所有property元素的属性dynamic_insert为true。 5. .. . ... 等价于所有property元素的属性dynamic_update为true。 注意:动态生成语句的系统开销很小,不影响性能。如果涉及的表包含多个字段,那我们应实现动态语句的生成。也就是说,我们可以只对需要插入或者更新的字段进行操作,这样可以节省SQL语句执行时间。 3.2 设置类的包名 通常情况下,我们在设置 之前我们所做的是一个映射文件包含一个类的映射,在复杂的项目中,为了避免映射文件过多,我们也可以在一个映射文件中包含多个类的映射。比如: …. …. …. 以上文件中映射了多个表和类,但是我们发现,每写一个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。 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。适合于跨数据库平台开发。