Spring数据库访问之ORM

Spring数据库访问中另外一大模块就是ORM,ORM即对象/关系映射。Spring支持大多数ORM框架,比如Hibernate,JPA,JDO,TopLink和iBatis(Spring2支持iBatis2,现MyBatis3的Spring支持由MyBatis社区开发,并非Spring)。

成都创新互联公司是由多位在大型网络公司、广告设计公司的优秀设计人员和策划人员组成的一个具有丰富经验的团队,其中包括网站策划、网页美工、网站程序员、网页设计师、平面广告设计师、网络营销人员及形象策划。承接:网站制作、成都网站制作、网站改版、网页设计制作、网站建设与维护、网络推广、数据库开发,以高性价比制作企业网站、行业门户平台等全方位的服务。

首先我们从单独使用ORM框架开始,来介绍Spring对ORM的支持,以Hibernate为例。使用ORM框架,需要提供持久化类,以课程管理为背景,如下设计课程类:

Java代码

 
 
 
 
  1. public class Course {   
  2.   private Long id;   
  3.   private String title;   
  4.   private java.util.Date startDate;   
  5.   private java.util.Date endDate;   
  6.   private int fee;   
  7.   //必须提供无参默认构造方法   
  8.   public Course() {   
  9.       super();   
  10.   }   
  11.   //省略其它构造方法,getter和setter等方法   
  12.  

作为对数据访问的一种模式,我们仍然应用DAO模式,写DAO类已经很熟练了,如下设计即可:

 
 
 
 
  1. package org.ourpioneer.course.dao;   
  2. import java.util.List;   
  3. import org.ourpioneer.course.bean.Course;   
  4. public interface CourseDAO {   
  5.     public void save(Course course);   
  6.     public void delete(Course course);   
  7. public void update(Course course);   
  8.     public Course findById(Long courseId);   
  9.     public List  findAll();     
  10. }  

非常简单的设计,包含CRUD操作,那么实现类中我们用Hibernate帮助我们进行数据库访问操作也非常简单:

 
 
 
 
  1. package org.ourpioneer.course.dao;   
  2. import java.util.List;   
  3. import org.hibernate.Query;   
  4. import org.hibernate.Session;   
  5. import org.hibernate.SessionFactory;   
  6. import org.hibernate.Transaction;   
  7. import org.hibernate.cfg.Configuration;   
  8. import org.ourpioneer.course.bean.Course;   
  9. public class CourseDAOImpl implements CourseDAO {   
  10.     private SessionFactory sessionFactory;   
  11.     public CourseDAOImpl() {   
  12.         Configuration cfg = new Configuration().configure();   
  13.         sessionFactory = cfg.buildSessionFactory();   
  14.     }   
  15.     public List  findAll() {     
  16.         Session session = sessionFactory.openSession();   
  17.         try {   
  18.             Query query = session.createQuery("from Course");   
  19.             return query.list();   
  20.         } finally {   
  21.             session.close();   
  22.         }   
  23.     }   
  24.     public Course findById(Long courseId) {   
  25.         Session session = sessionFactory.openSession();   
  26.         try {   
  27.             return (Course) session.get(Course.class, courseId);   
  28.         } finally {   
  29.             session.close();   
  30.         }   
  31.     }   
  32.     public void save(Course course) {   
  33.         Session session = sessionFactory.openSession();   
  34.         Transaction tx = session.beginTransaction();   
  35.         try {   
  36.             tx.begin();   
  37.             session.saveOrUpdate(course);   
  38.             tx.commit();   
  39.         } catch (RuntimeException e) {   
  40.             tx.rollback();   
  41.             throw e;   
  42.         } finally {   
  43.             session.close();   
  44.         }   
  45.     }   
  46. }  

这里只展示几个方法作为代表,其它方法类似可以写出,非常简单。首先是构造方法,初始化实现类时创建Hibernate的配置对象,new Configuration().configure()时,Hibernate会在类路径的根路径下自动寻找名为hibernate.cfg.xml的配置文件并加载,之后就是创建Hibernate的Session对象,利用Session对象提供和衍生出的方法来进行数据库操作。下面来看配置文件,这是比较重要的,因为通过配置文件,把数据库信息和实体Bean的信息都告诉Hibernate,可以省去我们很多在数据库设计上的事情。

 
 
 
 
  1. xml version='1.0' encoding='UTF-8'?>  
  2.           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"   
  3.   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  4.   
  5.       
  6.         com.mysql.jdbc.Driver property>  
  7.         jdbc:mysql:///test property>  
  8.         root property>  
  9.         123 property>  
  10.         org.hibernate.dialect.MySQLDialect property>  
  11.         true property>  
  12.         update property>  
  13.           
  14.      session-factory>  
  15. hibernate-configuration>  

这里我们告诉Hibernate使用mysql数据库,并配置数据库信息,所用方言,并在执行应用程序时在控制台打印出还原的SQL语句。使用hbm2ddl.auto可以让Hibernate根据实体Bean的配置信息来自动建表,这是很方便的,最后的mapping就是配置实体bean映射信息的文件,我们来看一下:

 
 
 
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  3.   
  4.       
  5.           
  6.               
  7.          id>  
  8.         
  9.             length="100" not-null="true" />  
  10.         
  11.             not-null="true" />  
  12.         
  13.             not-null="true" />  
  14.         
  15.             not-null="true" />  
  16.      class>  
  17. hibernate-mapping>  

这里首先配置了实体bean的所在位置,类信息还有数据库中表对应的关系。之后创建主键信息id,使用了MySQL的自增主键特性,剩下就是对各个字段的描述了,都见名知意,易于理解。

准备好这些内容,就可以编写测试程序了,在项目中引入Hibernate的相关依赖。这里说明一下,Maven默认仓库是Apache的,其中的Hibernate版本还在3.3.2.GA(本文编写时),而当前的Hibernate官方版本已经是3.6.0.Final了,我们想使用新版本,该怎么办?很简单,配置Maven仓库的位置,让其可以发现3.6.0.Final版的Hibernate并下载依赖。JBoss官方也提供一个Maven仓库,其中就有最新版的Hibernate,那么我们在项目的POM中配置一下这个地址:

 
 
 
 
  1.   
  2.       
  3.           
  4.             always updatePolicy>  
  5.          releases>  
  6.           
  7.             always updatePolicy>  
  8.          snapshots>  
  9.         Jboss id>  
  10.         Jboss Repository name>  
  11. https://repository.jboss.org/nexus/content/groups/public url>  
  12.      repository>  
  13. repositories>  

之后,为项目引入其它必要的依赖,使用Maven管理,我们不需自己再去寻找各种依赖了,非常简单的管理,如图所示:

下面来看示例程序:

 
 
 
 
  1. package org.ourpioneer.course;   
  2. import java.util.GregorianCalendar;   
  3. import java.util.List;   
  4. import org.ourpioneer.course.bean.Course;   
  5. import org.ourpioneer.course.dao.CourseDAO;   
  6. import org.ourpioneer.course.dao.CourseDAOImpl;   
  7. public class Demo {   
  8.     public static void main(String[] args) {   
  9.         CourseDAO courseDAO = new CourseDAOImpl();   
  10.         Course course = new Course();   
  11.         course.setTitle("Spring ORM");   
  12.         course.setStartDate(new GregorianCalendar(2011, 1, 1).getTime());   
  13.         course.setEndDate(new GregorianCalendar(2011, 2, 1).getTime());   
  14.         course.setFee(100);   
  15.         courseDAO.save(course);   
  16.         List  courses = courseDAO.findAll();     
  17.         Long courseId = courses.get(0).getId();   
  18.         course = courseDAO.findById(courseId);   
  19.         System.out.println(course);   
  20.         courseDAO.delete(course);   
  21.     }   
  22. }  

首先创建的是Course对象,并设置其中的属性,使用save方法将其持久化到数据库中,之后通过findAll方法查询数据库中的全部记录,当然现在只有一条。并拿到Id,在通过findById方法获取出来,然后打印结果。最终删除记录。执行该程序,我们可以得到如下输出信息:

我们之前并没有在数据库中建表,而Hibernate在执行插入之前会为我们自动建表,然后执行插入操作,两次查询操作,并打印出对象信息,最后执行了删除操作,从SQL语句中可以看到Hibernate最终的执行结果是什么。而此时回到数据库中,会发现一个建好的表。

Hibernate的简单ORM映射操作就介绍完了,下面来看使用JPA注解和Hibernate的API来持久化对象,首先修改持久化类:

 
 
 
 
  1. package org.ourpioneer.course.bean;   
  2. import java.sql.Date;   
  3. import javax.persistence.Column;   
  4. import javax.persistence.Entity;   
  5. import javax.persistence.GeneratedValue;   
  6. import javax.persistence.GenerationType;   
  7. import javax.persistence.Id;   
  8. import javax.persistence.Table;   
  9.   
  10. /**  
  11.  * 课程信息描述bean  
  12.  *   
  13.  * @author Nanlei  
  14.  *   
  15.  */  
  16. @Entity  
  17. @Table(name = "course")   
  18. public class Course {   
  19.     @Id  
  20.     @GeneratedValue(strategy = GenerationType.IDENTITY)   
  21.     @Column(name = "ID")   
  22.     private Long id;   
  23.     @Column(name = "TITLE", length = 100, nullable = false)   
  24.     private String title;   
  25.     @Column(name = "STARTDATE",nullable=false)   
  26.     private java.util.Date startDate;   
  27.     @Column(name = "ENDDATE",nullable=false)   
  28.     private java.util.Date endDate;   
  29.     @Column(name = "FEE",nullable=false)   
  30.     private int fee;   
  31.     // 其余内容不变,省略   
  32. }  

使用JPA的注解,首先对类进行注解,使用@Entity,并关联数据库表,使用@Table。下面就是对字段进行主键了,标识符(主键)字段要使用@Id,还要指定生成策略和对应的列名,剩下的字段只需指定列信息即可。现在告诉Hibernate我们使用JPA注解,而不使用映射文件了,如下配置:

 
 
 
 
  1.   
  2.   

修改DAO实现类的构造方法,使用注解配置方式创建SessionFactory,如下即可:

 
 
 
 
  1. public CourseDAOImpl() {   
  2.     // Configuration cfg = new Configuration().configure();   
  3.     Configuration cfg = new AnnotationConfiguration().configure();   
  4.     sessionFactory = cfg.buildSessionFactory();   
  5. }  

此时再次执行测试方法,反馈的信息没有任何变化,但是我们就使用了JPA注解而并非Hibernate的映射信息了。下面来看看使用Hibernate作为JPA引擎的持久化步骤。先配置依赖,引入:

 
 
 
 
  1.   
  2.     org.hibernate groupId>  
  3.     hibernate-entitymanager artifactId>  
  4.     3.6.0.Final version>  
  5.     jar type>  
  6.     compile scope>  
  7. dependency>  
  8.   
  9.     jboss groupId>  
  10.     jboss-archive-browsing artifactId>  
  11.     5.0.0alpha-200607201-119 version>  
  12.     jar type>  
  13.     compile scope>  
  14. dependency>  

如果在Java EE容器中运行JPA,可以通过容器来配置JPA,如果是在Java SE中运行JPA,那么需要在类路径的META-INF下配置persistence.xml来配置持久化单元,在本例中我们使用Hibernate作为JPA的引擎,就可以这么来写:

 
 
 
 
  1. '1.0' encoding='UTF-8'?>  
  2. "http://java.sun.com/xml/ns/persistence"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence   
  5. http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"   
  6.     version="1.0">  
  7.      "course">    
  8.              
  9.              "hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />    
  10.           
  11.       
  12.   

加载配置文件仍然使用Hibernate的配置文件,或者也可以将其中的property写在persistence.xml中,那么因为在这里JPA已经可以获取持久化单元了,在Hibernate的配置中就需要配置持久化对象的映射了,去掉mapping信息即可。有了配置信息,还需要实现类,我们重写一个JPA的DAO实现,如下:

Java代码

 
 
 
 
  1. package org.ourpioneer.course.dao;   
  2. import java.util.List;   
  3. import javax.persistence.EntityManager;   
  4. import javax.persistence.EntityManagerFactory;   
  5. import javax.persistence.EntityTransaction;   
  6. import javax.persistence.Persistence;   
  7. import javax.persistence.Query;   
  8. import org.ourpioneer.course.bean.Course;   
  9. public class CourseDAOImplJPA implements CourseDAO {   
  10.     private EntityManagerFactory entityManagerFactory;   
  11.     public CourseDAOImplJPA() {   
  12.         entityManagerFactory = Persistence.createEntityManagerFactory("course");   
  13.     }   
  14.     public void delete(Course course) {   
  15.         EntityManager manager = entityManagerFactory.createEntityManager();   
  16.         EntityTransaction tx = manager.getTransaction();   
  17.         try {   
  18.             tx.begin();   
  19.             manager.remove(manager.merge(course));   
  20.             tx.commit();   
  21.         } catch (RuntimeException e) {   
  22.             tx.rollback();   
  23.             throw e;   
  24.         } finally {   
  25.             manager.close();   
  26.         }   
  27.     }   
  28.     public List  findAll() {     
  29.         EntityManager manager = entityManagerFactory.createEntityManager();   
  30.         try {   
  31.             Query query = manager   
  32.                     .createQuery("select course from Course course");   
  33.             return query.getResultList();   
  34.         } finally {   
  35.             manager.close();   
  36.         }   
  37.     }   
  38.     public Course findById(Long courseId) {   
  39.         EntityManager manager = entityManagerFactory.createEntityManager();   
  40.         try {   
  41.             return manager.find(Course.class, courseId);   
  42.         } finally {   
  43.             manager.close();   
  44.         }   
  45.     }   
  46.     public void save(Course course) {   
  47.         EntityManager manager = entityManagerFactory.createEntityManager();   
  48.         EntityTransaction tx = manager.getTransaction();   
  49.         try {   
  50.             tx.begin();   
  51.             manager.persist(course);   
  52.             tx.commit();   
  53.         } catch (RuntimeException e) {   
  54.             tx.rollback();   
  55.             throw e;   
  56.         } finally {   
  57.             manager.close();   
  58.         }   
  59.     }   
  60.     public void update(Course course) {   
  61.         EntityManager manager = entityManagerFactory.createEntityManager();   
  62.         EntityTransaction tx = manager.getTransaction();   
  63.         try {   
  64.             tx.begin();   
  65.             manager.merge(course);   
  66.             tx.commit();   
  67.         } catch (RuntimeException e) {   
  68.             tx.rollback();   
  69.             throw e;   
  70.         } finally {   
  71.             manager.close();   
  72.         }   
  73.     }   
  74. }  

这里特别要注意的是delete方法,首先调用merge方法,否则当前对象是出于脱管态的,无法和Session进行关联,也就无法删除该对象。不加merge方法时候会抛出异常,大家可以测试一下,因为底层还是Hibernate进行的,Hibernate的持久化对象有三种状态,那么就要注意状态发生的变化。

#p#

现在我们来看如何在Spring中配置ORM资源工厂,也就是在Spring中使用ORM框架。仍然以Hibernate为例来说明,要引入spring-orm和spring-context模块来做测试。首先我们可以修改一下DAO实现类的写法,因为用了Spring,就不用显式来new对象了,那么对于Hibernate的SessionFactory,使用注入的方式来进行配置,修改CourseDAOImpl类,如下设置:

 
 
 
 
  1. private SessionFactory sessionFactory;   
  2. public void setSessionFactory(SessionFactory sessionFactory) {   
  3.     this.sessionFactory = sessionFactory;   
  4. }  

去掉构造方法,为sessionFactory提供get方法即可。之后就是配置Spring了,很简单,要配置courseDao和sessionFactory:

 
 
 
 
  1. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  2.       
  3. bean>  
  4.   
  5.      property>  
  6. bean> 

把Hibernate配置对象的映射文件加上,之后修改测试方法,从Spring的容器中获取对象就可以了:

 
 
 
 
  1. ApplicationContext ctx = new ClassPathXmlApplicationContext(   
  2.         "classpath:applicationContext.xml");   
  3. CourseDAO courseDAO = (CourseDAO) ctx.getBean("courseDao");  

此时,我们还依赖Hibernate的配置文件,那么完全可以把Hibernate中的配置信息移入Spring之中,因为Spring的ORM模块完全支持Hibernate,可以如下进行,我们使用C3P0作为连接池:

 
 
 
 
  1.     scope="singleton" destroy-method="close">  
  2.       
  3.       
  4.       
  5.       
  6. bean>  

将数据库的基本信息配置好后,数据源的配置就完成了。下面是配置Hibernate:

 
 
 
 
  1. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  2.       
  3.     
  4.         value="classpath:org/ourpioneer/course/hbm/*.hbm.xml" />  
  5.       
  6.           
  7.             org.hibernate.dialect.MySQLDialect prop>  
  8.             true prop>  
  9.             update prop>  
  10.          props>  
  11.      property>  
  12. bean>  

这里我们将实体映射一起配置进来,使用了*通配符,并配置了基本的Hibernate属性,比如方言,显示sql语句和自动建表。剩下的就是DAO的配置了,它不用做什么修改,仍然注入sessionFactory即可,然后执行测试:

从中可以看到启动信息和Hibernate生成的SQL语句。除了使用Hibernate的实体映射文件外,我们还可以使用注解,之前已经在Course持久化类中添加了注解,那么我们就来配置使用注解的方式,很简单,只需修改Spring中的Hibernate SessionFactory配置即可,如下:

 
 
 
 
  1. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  2.       
  3.       
  4.           
  5.             org.ourpioneer.course.bean.Course value>  
  6.          list>  
  7.      property>  
  8.       
  9.           
  10.             org.hibernate.dialect.MySQLDialect prop>  
  11.             true prop>  
  12.             update prop>  
  13.          props>  
  14.      property>  
  15. bean>  

这样就使用在持久化类中的注解信息而不需要单独编写HBM映射文件了,执行测试,结果是一样的。当然,在Spring中,还可以使用JPA的EntityManager来进行数据的持久化操作,那么又如何来进行呢?和前面介绍的类似,首先在JPA的DAO实现类中修改EntityManager的配置方式,使用注入来进行:

 
 
 
 
  1. private EntityManagerFactory entityManagerFactory;   
  2. public void setEntityManagerFactory(   
  3.         EntityManagerFactory entityManagerFactory) {   
  4.     this.entityManagerFactory = entityManagerFactory;   
  5. }  

同理,修改Spring的配置文件,配置EntityManagerFactory,如下:

 
 
 
 
  1. class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">  
  2.       
  3. bean>  

因为配置了persistenceUnitName,那么不要忘记了在META-INF目录下的persistence.xml文件,其中是这么写的:

 
 
 
 
  1.   
  2.       
  3.           
  4.      properties>  
  5. persistence-unit>  
网站栏目:Spring数据库访问之ORM
浏览地址:http://www.shufengxianlan.com/qtweb/news18/284518.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联