JAVA 开发平台的技术和框架(四)二、ORM :Hibernate ibatis

ORM

以下摘自百度百科:

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。

面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。

对象关系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。ORM方法论基于三个核心原则: 简单:以最基本的形式建模数据。 传达性:数据库结构被任何人都能理解的语言文档化。 精确性:基于数据模型创建正确标准化了的结构。 典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。

 JDBC和ORM

以下内容摘自:http://blog.csdn.net/wwwtyb/article/details/5469597 


       1、繁琐的代码问题:
       用JDBC的API编程访问数据库,代码量较大,特别是访问字段较多的表的时候,代码显得繁琐、累赘,容易出错,例如:
       程序员需要耗费大量的时间、精力去编写具体的数据库访问的SQL语句,还要十分小心其中大量重复的源代码是否有疏漏,并不能集中精力于业务逻辑开发上面。
       ORM则建立了Java对象与数据库对象之间的映射关系,程序员不需要编写复杂的SQL语句,直接操作Java对象即可,从而大大降低了代码量,也使程序员更加专注于业务逻辑的实现。
       2、数据库对象连接问题
       关系数据对象之间,存在各种关系,包括1对1、1对多、多对1、多对多、级联等。在数据库对象更新的时候,如果采用JDBC编程,程序员必须十分小心处理这些关系,以保证维持这些关系不会出现错误,而这个过程是一个很痛苦的过程。
       ORM建立Java对象与数据库对象关系映射的同时,也自动根据数据库对象之间的关系创建Java对象的关系,并且提供了维持这些关系完整、有效的机制。
       3、系统架构问题
       现在的应用系统,一般由展示层、业务逻辑层、数据访问层、数据库层等组成,各层次功能划分非常清晰。JDBC属于数据访问层,但是使用JDBC编程时,程序员必须知道后台是用什么数据库、有哪些表、各个表有有哪些字段、各个字段的类型是什么、表与表之间什么关系、创建了什么索引等等与后台数据库相关的详细信息。相当于软件程序员兼职数据库DBA。
       使用ORM技术,可以将数据库层完全隐蔽,呈献给程序员的只有Java的对象,程序员只需要根据业务逻辑的需要调用Java对象的Getter和 Setter方法,即可实现对后台数据库的操作,程序员不必知道后台采用什么数据库、有哪些表、有什么字段、表与表之间有什么关系。
       于是,系统设计人员把ORM搭建好后,把Java对象交给程序员去实现业务逻辑,使数据访问层与数据库层清晰分界。
       4、性能问题
       采用JDBC编程,在很多时候存在效率低下的问题,如:
       pstmt =conn.prepareStatement("insert into user_info values(?,?)");
       for (int i=0; i<1000; i++) {
          pstmt.setInt(1,i);
          pstmt.setString(2,"User"+i.toString());
          pstmt.executeUpdate();
       }
       以上程序将向后台数据库发送1000次SQL语句执行请求,运行效率较低。
       如果采用ORM技术,ORM框架将根据具体数据库操作需要,会自动延迟向后台数据库发送SQL请求,如上面的程序,只会在循环完成后,一次向数据库发送操作请求,从而大大降低通讯量,提高运行效率;ORM也可以根据实际情况,将数据库访问操作合成,尽量减少不必要的数据库操作请求。

以下内容摘自:http://article.yeeyan.org/view/213582/180283  iBATIS、Hibernate和JPA:哪一款最适合你

http://blog.chinaunix.net/uid-9288192-id-80368.html iBATIS, Hibernate, and JPA: Which is right for you
 

持久性

持久性(persistence是数据的一个属性,其确保即使是在应用的生命周期之外数据也是可用的。对于像Java这样的面向对象语言来说,持久性确保了即使是在创建对象的应用停止执行之后对象的状态仍是可访问的。

存在多种实现持久性的方法。传统的解决这一问题的方法是使用文件系统来把需要的信息存储在平面文件(flat file)中。这一方法很难用来管理大量的数据,因为数据分布在不同的文件中。使用平面文件系统的话维护数据的一致性也是一个问题,因为相同的信息可能会被重复放在各个文件中。在平面文件中查找数据很耗时,特别是如果这些文件还未排序的话。还有,文件系统对并发访问的支持有限,因为它们不能确保数据的完整性。基于上述种种原因,在寻求持久性时,文件系统并不被视为一个良好的数据存储解决方案。

当前最常见的方法是使用数据库,其充当巨大量数据的存储库。存在许多种类型的数据库:关系型的、层次结构型的、网络型的、面向对象型的等等。这些数据库,以及它们的数据库管理系统(DBMS),不仅提供持久性能力,而且管理其所持久的信息。关系数据库是最被广泛使用的类型,关系数据库中的数据被建模成一组相互关联的表。

企业级应用的出现普及了n层架构,其目的是通过把表现、业务和数据库相关代码分离到应用的不同层级(或是层面)中来提升可维护性。分离了业务逻辑和数据库代码的层面即是持久层,其保持了应用相对于底层的数据库技术的独立性。适当的位置上有了这一强健的层面,开发者就不再需要操心数据的持久性。持久层封装了存储和检索关系型数据库中的数据的方式。

Java应用传统上使用JDBCJava Database ConnectivityAPI来把数据持久到关系数据库中。JDBC API使用SQL语句来完成创建(create)、读取(read)、更新(update)和删除(delete)(CRUD)操作。JDBC代码内嵌在Java类中——换句话说,这类代码与业务逻辑紧密耦合在一起。这类代码还在很大程度上依赖于SQL,而SQL并非是跨数据库的标准;这使得从一种数据库移植到另一种数据库变得困难起来。

关系数据库技术强调的是数据及其之间的关系,而用于Java中的面向对象范式却并非关注数据本身,而是关注执行于数据之上的操作。因此,当这两种技术需要携手合作时,就会存在利益冲突。而且,关系数据库并不能满足继承、多态及关联这些面向对象编程概念。当Java应用中的用户定义的数据类型被映射到关系数据库上时,由这一失配导致的另一个问题就出现了,因为后者并没有提供所需的类型支持。

对象关系映射

对象关系映射(object-relational mappingORM)已成为了有时被称作对象关系阻抗失配(impedance mismatch)的这一问题的一个解决方案。ORM是一种透明地把应用对象持久到关系数据库中的表的技术。ORM的行为就像是一个虚拟的数据库,对用户隐藏了底层的数据库架构。ORM提供功能来执行完整的CRUD操作并鼓励面向对象的查询。ORM还支持元数据映射以及在应用的事务管理方面提供帮助。

举个例子有助于说明ORM是如何工作的。考虑一个需要持久到数据库中的简单的Car对象,领域模型中的这一Car对象是数据模型中的CAR表的表现形式。Car对象的属性派生自CAR表的各列。在Car类和CAR表之间存在一个直接映射,如图1中的说明。

1. 把对象映射到表上

存在许多开源的ORM工具,其中包括HibernateiBATIS SQL Maps以及Java Ultra-Lite Persistence等。这些工具大多数是提供Java应用和数据库之间的抽象层的持久性框架。持久性框架把应用领域中的对象映射成需要持久在数据库中的数据,这些映射可使用XML文件或是元数据注解(后者作为Java1.5的组成部分被引入到语言中)来定义。持久性框架的目的是分离数据库相关代码和应用代码(即业务逻辑),从而提高应用的灵活性。持久性框架通过提供一个持久性逻辑的包装器来简化开发过程。

iBATIS:直接使用SQL

对象-关系映射(ORM)使用直接映射来生成内部的JDBC或是SQL代码。然而对于一些应用场景来说,你需要对SQL查询做更加直接的控制。在编写涉及了一系列更新查询的应用时,直接编写自己的SQL查询比依赖于ORM生成的SQL来得更有效一些。另外,在对象模型和数据模型之间存在失配时,ORM是不能够使用的。正如我们提到过的那样,JDBC代码一度是这类问题最常见的解决方案,但是它在应用代码内部引入了许多的数据库代码,使得应用更加难以维护。这里需要一个持久层来解耦应用和数据库。

iBATIS Data Mapper框架有助于解决这些问题。iBATIS是一个持久性框架,其提供了SQL的好处却又免去了JDBC的复杂性。与其他大多数的持久性框架不同,iBATIS鼓励直接使用SQL,并确保所有的SQL好处没有被框架本身覆盖掉。

简单是iBATIS最大的优势,因为它提供一个简单的映射和用于构建数据访问代码的API层。在这一框架中,数据模型和对象模型不需要做精确的彼此映射。这是因为iBATIS使用了一个数据映射器(data mapper,其经由一个XML描述符而不是元数据映射器把对象映射到存储过程、SQL语句或是ResultSet上,而元数据映射器起的是把领域中的对象映射到数据库中的表上的作用。因此,iBATIS能够使得数据模型和对象模型彼此独立,互不相干。

iBATIS简介

    iBATIS项目最初由Cinton Begin发起并在2001年发布。这一持久性框架最初是为Java设计的,然而后来已经被扩展以支持其他的平台,这其中包括.NetRuby

 

iBATIS的工作方式

iBATIS通过把数据库的输入输出映射到领域对象上来支持数据库和应用之间的松散耦合,并由此而引入了一个抽象层。映射是通过使用包含了SQL查询的XML文件来完成的。这一松散耦合允许映射在应用和数据库设计失配的系统上工作,它还有助于用来处理传统遗留数据库和随时间发生变化的数据库。

iBATIS框架主要使用下面的两个XML文件作为描述符:

Ÿ           SQLMapConfig.xml

Ÿ           SQLMap.xml

SQLMapConfig.xml

SQLMapConfig.xml是一个主要的XML文件,其包含所有的配置细节,比如数据源这一类的数据细节等;它还可以选择在其中包含关于事务管理的信息。该文件标识了所有的SQLMap.xml文件——可能有不止一个这样的文件——并加载它们。

考虑这样一个映射到数据库中的EMPLOYEE表上的Employee类,类的属性——emp_id,emp_firstnameemp_lastname——对应于表中的相似名字列。Employee类的类图如图2所示。(该类会被用来说明本文中讨论的不同的持久性技术。)

2. Employee类的类图

Employee类的SQLMapConfig.xml文件可以写成清单1所示的内容。

清单1. Employee类的SQLMapConfig.xml文件

 


	
		
			
			
			
			
		
	 
	

 

SQLMapConfig.xml使用transactionManager标签来配置给这一特定的SQL映射使用的数据源。其指定数据源的类型以及一些细节,其中包括驱动程序、数据库URL以及用户名称和用户密码等信息。sqlMap标签则指定SQLMap.xml文件的位置,以便加载它。

SQLMap.xml

另一个XML文件是SQLMap.xml,该文件在其相关到某个表后再做实际命名。在单个应用中可能就会存在任意数量的这种文件,这一文件是把领域对象映射到SQL语句的地方。这一描述符使用参数映射来把输入映射到语句上,并使用结果映射来映射SQLResultSet。该文件还包含了查询,因此,要改变查询的话,你需要修改的是XML而非应用的Java代码。映射是通过使用实际的要和数据库交互的SQL语句来完成的。所以,使用SQL给开发者提供了更大的灵活性,并使得iBATIS对于有使用SQL编程经验的人来说变得更容易理解。

定义了在EMPLOYEE表上执行CRUD操作的SQL语句的SQLMap.xml文件如清单2所示。

清单2. 用于在EMPLOYEE上执行操作的SQLMap.xml


	
	
		
		
		
	  
	
	
		 insert into EMPLOYEE (
			emp_id, emp_firstname, emp_lastname) values ( #id#, #firstName# ,
			#lastName# )  
		 update EMPLOYEE set
			emp_firstname = #firstName#, emp_lastname = #lastName# where emp_id =
			#id#  
		 delete from EMPLOYEE
			where emp_id = #id#  

在清单2中,typeAlias标签被用来表示类型的别名,这样就可以避免在每次类名出现的时候都要输入完整的类名。其包含了resltMap标签,该标签描述了从查询中返回的列和Employee类所表示的类属性之间的映射。resultMap是可选的,如果表(或别名)中的列与类属性完全匹配的话就不需要resultMap。跟在这一resultMap标签后面的是一系列的查询,SQLMap.xml可以包含任意数目的查询。所有的这些selectinsertupdatedelete语句都写在各自的标签内部,每个语句都使用id属性来命名。

来自select查询的输出可以映射到一个resultMap或是一个JavaBean结果类上。查询中的别名应该与目标结果类(即该JavaBean)中的属性相匹配。parameterClass属性被用来指定其属性作为输入的JavaBean,这一哈希符号内的任何参数都是该JavaBean的属性。

加载描述符文件到Java应用中

在完成了整个的配置和在两个XML文件中都做了映射之后,SQLMapConfig.xml文件需要由Java应用来加载。第一步是加载早先创建的SQLMap.xml配置文件,要做到这一点的话,你需要用到com.ibatis.common.resources.Resources类,该类已包含在iBATIS框架中,如清单3所示。 

清单3. 加载SQLMap.xml

private static SqlMapClient sqlMapper;

...    try {         Reader reader = Resources.getResourceAsReader("com/mydomain/data/SqlMapConfig.xml");         sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);         reader.close();       } catch (IOException e) {         // Fail fast.         throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);       }     }

SqlMapClient类用来与SQLMap一起工作,其允许运行诸如select、insert、update一类的已映射语句。SqlMapClient对象是线程安全的,因此,一个对象就足够了,这也使得把它用作一个静态成员成为了一种不错的选择。该对象通过读入一个SQLMapConfig.xml文件来创建,iBATIS框架提供了Resources.getResourceAsReader()这一实用方法,你可以使用该方法来读入SQLMapConfig.xml文件。因此,通过使用SQLMap的这一实例,你可以访问来自数据库的对象——在这一例子中,是Employee对象。

为了调用针对EMPLOYEE表的操作,SQLMap提供了不同的方法,比如其中就包括queryForList()、queryForObject()、insert()、update()和queryForMap()等。清单4中展示的queryForList()方法返回Employee对象的一个列表。

清单4. queryForList()

sqlMapper.queryForList("selectAllEmps");

同样地,当只有一行内容作为查询结果返回时,应该使用queryForObject()方法。这两个方法都使用语句名作为参数。

相应的方法可用于执行insertupdatedelete操作,如清单5所示。这些方法既要用到SQLMap.xml文件中声明的语句名,也要用到Employee对象作为输入。

清单5. insertupdatedelete操作

sqlMapper.insert("insertEmp", emp);

sqlMapper.update("updateEmp", emp);

sqlMapper.delete("deleteEmp", id);

这样,Java对象就可以使用iBATISJava对象中的直接的SQL语句来持久化了。

何时使用iBATIS

iBATIS最好是用在你需要全面地控制SQL的时候,在需要对SQL查询做微调的时候也很有用。当你在应用和数据库设计两方面都有完全的控制权的时候,就不应该使用iBATIS,因为在这样的情况下,应用可能会做出修改以适应数据库,或是反过来。在这种情形中,你可以构建一个完全的对象-关系应用,其他的ORM工具更适于使用,因为iBATIS较为以SQL为中心,其通常被称作反转的——功能齐全的ORM工具生成SQL,而iBATIS直接使用SQLiBATIS也不适合于非关系型的数据库,因为这类数据库不支持事务和其他iBATIS用到的键特性。

Hibernate

Hibernate是一个开源的轻量级的对象-关系映射解决方案。Hibernate的主要特点是支持基于对象的建模,这使得它可以提供一个透明的持久性机制。其使用XML来把数据库映射到应用上,并且支持细粒度的对象。Hibernate的当前版本是4.x,该版本支持Java注解(annotation),因此是满足EJB规范的。

Hibernate包含了一种被称作Hibernate Query Language或是HQL的非常强大的查询语言。HQL非常类似SQL,不过还定义了一些额外的约定。HQL是完全面向对象的,能够充分利用继承、多态和关联等这些面向对象核心概念的长处。除了被用到的Java类和属性的名称之外,HQL查询是非大小写敏感的。HQL把查询结果作为对象返回,这些对象可以由编程者直接访问和操纵。HQL还支持分页和动态分析(profiling)等许多高级功能,SQL一直未提供对这些功能的支持。在用到多个表来工作时,HQL并不要求做任何显式的连接(join)。

Hibernate简介

    Hibernate是由Gavin King带领的一个团队开发出来。Hibernate的开发始于2001年,该团队后来被JBoss收购,Hibernate现由JBoss管理。Hibernate最初是为Java开发的;在2005年引入了命名为NHibernate.Net版本。

为什么我们需要Hibernate?

传统上用于对象-关系映射的实体beanentity bean)非常难以理解和维护,Hibernate使得对象-关系映射变得简单起来,它的方法是在一个XML文件中映射元数据,该文件定义了需要映射到某个特定类上的数据库中的表。在其他的持久性框架中,你需要修改应用类来实现对象-关系映射;而在Hibernate中则不需要这样做。

使用了Hibernate后,你就无需担心数据库的改变,因为手工修改SQL脚本文件的工作已被免除。如果你需要不时改变应用使用到的数据库的话,也可以通过修改配置文件中的dialet属性来很容易地解决这一问题。Hibernate提供了全部的SQL功能,其中的有些是早先的商业ORM框架一直没有提供的。Hibernate也支持许多的数据库,其中包括MySQLOracleSybaseDerbyPostgreSQL等,而且也能够与基于简单Java对象(plain old Java objectPOJO)的模型配合得很好。

Hibernate基于所选择的底层数据库来生产JDBC代码,因此省去了编写JDBC代码的麻烦,它还支持连接的池化。Hibernate使用的API很简单也很容易学习,只有很少SQL知识的开发者也能够使用Hibernate,因为它减轻了编写SQL查询的负担。

Hibernate架构

就内部来说,Hibernate用到了JDBCJDBC提供了数据库的一个抽象层,它同时也采用了Java Transaction APIJTA)和JNDI来集成其他应用。Hibernate需要用来与数据库交互的连接信息由JDBC连接池提供,这需要做配置。

Hibernate的架构主要由两个接口——SessionTransaction组成——以及一个Query接口,该接口位于应用的持久层中。定义于应用的业务层中的类通过Hibernate持久层的独立元数据来进行交互,持久层转而使用某些JDBC API来与数据库层对话。此外,Hibernate还用到了其他的配置接口,其中主要是有着适当命名的Configuration类。Hibernate还使用回调接口和一些用于扩展映射功能的可选接口。完整的Hibernate架构如图3所示。未找到原图

JAVA 开发平台的技术和框架(四)二、ORM :Hibernate ibatis_第1张图片

下面是Hibernate组成部分的主要编程接口:

Ÿ           org.hibernate.SessionFactory基本上是用来获取一个session实例,并且可看作是连接池化机制的一个模拟。这是线程安全的,因为所有的应用线程都使用单一的SessionFactory(只要Hibernate只使用一个数据库)。该接口通过配置文件来配置,配置文件决定了要加载的映射文件。

Ÿ           org.hibernate.Session提供了一个单独的线程,该线程确定应用和数据库之间的对话。这是对一个特定(单个)连接的模拟。该接口是非常轻量级的,而且是非线程安全的。

Ÿ           org.hibernate.Transaction提供了一个单线程对象,其横跨整个应用并确定原子工作单元。其基本上抽象了JDBCJTACORBA事务。

Ÿ           org.hibernate.Query被用来执行查询,或以HQL的形式或是以底层数据库的SQL方言形式。Query实例是轻量级的,需要提到的很重要的一点是,它不能用在创建它的session的外部。

配置Hibernate

Hibernate通过一个名为hibernate.cfg.xmlXML文件来做配置。该配置文件提供建立到特定关系数据库的连接方面的帮助,配置文件应该要知道其需要引用哪些映射文件。在运行时,Hibernate读入映射文件,然后使用映射文件来构建一个动态的与数据库表相对应的Java类。一个示例的配置文件如清单6所示。

清单6. hibernate.cfg.xml


	    
		 jdbc:mysql://localhost/hibernateDemo     
		 com.mysql.jdbc.Driver     
		root 
		infosys      
		 org.hibernate.dialect.MySQLDialect     
		false
		
			org.hibernate.transaction.JDBCTransactionFactory     
		
	

 

使用Hibernate工作

当在应用中创建了一个SessionFactory实例时,Hibernate读入配置文件并标识出各自的映射文件。创建自SessionFactorysession对象获取到数据库的一个特定连接,这个session对象就是持久化类实例的持久化上下文。实例可以是以下三种状态之一:瞬态的(transient)、持久的(persistent)或是游离的(detached)。处于瞬态时,对象尚未与表关联起来;处于持久态中时,对象是与表关联的;而处于游离态中时,则不能保证对象与表是同步的。用来持久一个Employee对象的Hibernate代码如清单7所示。

清单7. 使用Hibernate来持久一个对象

Session session = null;
Transaction tx = null;
// At this point theConfiguration file is read                                                                                   SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
// A specific session object is obtained
session = sessionFactory.openSession();
// A new database transaction is
startedtx = session.beginTransaction();
//Employee Object is created & populated
Employee emp = new Employee();
emp.setId(1);
emp.setEmpFirstname("KL");
emp.setEmpLastname("Nitin");
// Using the session, emp object is persisted in the database
session.save(emp);

配置文件标识的映射文件把某个特定的持久类映射到数据库表上。它把特定的列映射到特定的字段上,并且具备关联、集合、主键映射以及ID键生成机制。映射文件一般根据其映射到表来命名,在我们的示例应用中,你应该使用Employee.hbm.xml作为对应于EMPLOYEE表的文件的名称。如你在清单8中见到的那样,映射文件指定Employee类需要映射到数据库中EMPLOYEE表上,该表有名为idemp_firstnameemp_lastname的三列,id是主键,必须要赋予某个值。

清单8. Employee.hbm.xml


	
		false
		
			
		
		
		
	

何时使用Hibernate

Hibernate最适合用来作为端到端的OR映射的手段。其提供了一个完整的ORM解决方案,但但是不会让你控制查询。对于那些对应用和数据库两者都有完全的控制权的情况来说,Hibernate是一种理想的解决方案。在这类情况中,你可以修改应用来适用数据库,反之亦然,在这些情况下你可以使用Hibernate来构建一个全对象-关系应用。对于不太熟悉SQL的面向对象编程者来说,Hibernate是最佳选择。

 

 

你可能感兴趣的:(java)