新聞中心
Spring數(shù)據(jù)庫訪問中另外一大模塊就是ORM,ORM即對象/關系映射。Spring支持大多數(shù)ORM框架,比如Hibernate,JPA,JDO,TopLink和iBatis(Spring2支持iBatis2,現(xiàn)MyBatis3的Spring支持由MyBatis社區(qū)開發(fā),并非Spring)。

成都創(chuàng)新互聯(lián)公司是由多位在大型網(wǎng)絡公司、廣告設計公司的優(yōu)秀設計人員和策劃人員組成的一個具有豐富經(jīng)驗的團隊,其中包括網(wǎng)站策劃、網(wǎng)頁美工、網(wǎng)站程序員、網(wǎng)頁設計師、平面廣告設計師、網(wǎng)絡營銷人員及形象策劃。承接:網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)站改版、網(wǎng)頁設計制作、網(wǎng)站建設與維護、網(wǎng)絡推廣、數(shù)據(jù)庫開發(fā),以高性價比制作企業(yè)網(wǎng)站、行業(yè)門戶平臺等全方位的服務。
首先我們從單獨使用ORM框架開始,來介紹Spring對ORM的支持,以Hibernate為例。使用ORM框架,需要提供持久化類,以課程管理為背景,如下設計課程類:
Java代碼
- public class Course {
- private Long id;
- private String title;
- private java.util.Date startDate;
- private java.util.Date endDate;
- private int fee;
- //必須提供無參默認構(gòu)造方法
- public Course() {
- super();
- }
- //省略其它構(gòu)造方法,getter和setter等方法
作為對數(shù)據(jù)訪問的一種模式,我們?nèi)匀粦肈AO模式,寫DAO類已經(jīng)很熟練了,如下設計即可:
- package org.ourpioneer.course.dao;
- import java.util.List;
- import org.ourpioneer.course.bean.Course;
- public interface CourseDAO {
- public void save(Course course);
- public void delete(Course course);
- public void update(Course course);
- public Course findById(Long courseId);
- public List findAll();
- }
非常簡單的設計,包含CRUD操作,那么實現(xiàn)類中我們用Hibernate幫助我們進行數(shù)據(jù)庫訪問操作也非常簡單:
- package org.ourpioneer.course.dao;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.hibernate.cfg.Configuration;
- import org.ourpioneer.course.bean.Course;
- public class CourseDAOImpl implements CourseDAO {
- private SessionFactory sessionFactory;
- public CourseDAOImpl() {
- Configuration cfg = new Configuration().configure();
- sessionFactory = cfg.buildSessionFactory();
- }
- public List findAll() {
- Session session = sessionFactory.openSession();
- try {
- Query query = session.createQuery("from Course");
- return query.list();
- } finally {
- session.close();
- }
- }
- public Course findById(Long courseId) {
- Session session = sessionFactory.openSession();
- try {
- return (Course) session.get(Course.class, courseId);
- } finally {
- session.close();
- }
- }
- public void save(Course course) {
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- try {
- tx.begin();
- session.saveOrUpdate(course);
- tx.commit();
- } catch (RuntimeException e) {
- tx.rollback();
- throw e;
- } finally {
- session.close();
- }
- }
- }
這里只展示幾個方法作為代表,其它方法類似可以寫出,非常簡單。首先是構(gòu)造方法,初始化實現(xiàn)類時創(chuàng)建Hibernate的配置對象,new Configuration().configure()時,Hibernate會在類路徑的根路徑下自動尋找名為hibernate.cfg.xml的配置文件并加載,之后就是創(chuàng)建Hibernate的Session對象,利用Session對象提供和衍生出的方法來進行數(shù)據(jù)庫操作。下面來看配置文件,這是比較重要的,因為通過配置文件,把數(shù)據(jù)庫信息和實體Bean的信息都告訴Hibernate,可以省去我們很多在數(shù)據(jù)庫設計上的事情。
- xml version='1.0' encoding='UTF-8'?>
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
com.mysql.jdbc.Driver property> jdbc:mysql:///test property> root property> 123 property> org.hibernate.dialect.MySQLDialect property> true property> update property> - session-factory>
- hibernate-configuration>
這里我們告訴Hibernate使用mysql數(shù)據(jù)庫,并配置數(shù)據(jù)庫信息,所用方言,并在執(zhí)行應用程序時在控制臺打印出還原的SQL語句。使用hbm2ddl.auto可以讓Hibernate根據(jù)實體Bean的配置信息來自動建表,這是很方便的,最后的mapping就是配置實體bean映射信息的文件,我們來看一下:
- xml version="1.0" encoding="UTF-8"?>
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- id>
- length="100" not-null="true" />
- not-null="true" />
- not-null="true" />
- not-null="true" />
- class>
- hibernate-mapping>
這里首先配置了實體bean的所在位置,類信息還有數(shù)據(jù)庫中表對應的關系。之后創(chuàng)建主鍵信息id,使用了MySQL的自增主鍵特性,剩下就是對各個字段的描述了,都見名知意,易于理解。
準備好這些內(nèi)容,就可以編寫測試程序了,在項目中引入Hibernate的相關依賴。這里說明一下,Maven默認倉庫是Apache的,其中的Hibernate版本還在3.3.2.GA(本文編寫時),而當前的Hibernate官方版本已經(jīng)是3.6.0.Final了,我們想使用新版本,該怎么辦?很簡單,配置Maven倉庫的位置,讓其可以發(fā)現(xiàn)3.6.0.Final版的Hibernate并下載依賴。JBoss官方也提供一個Maven倉庫,其中就有最新版的Hibernate,那么我們在項目的POM中配置一下這個地址:
always updatePolicy> - releases>
always updatePolicy> - snapshots>
Jboss id> Jboss Repository name> https://repository.jboss.org/nexus/content/groups/public url> - repository>
- repositories>
之后,為項目引入其它必要的依賴,使用Maven管理,我們不需自己再去尋找各種依賴了,非常簡單的管理,如圖所示:
下面來看示例程序:
- package org.ourpioneer.course;
- import java.util.GregorianCalendar;
- import java.util.List;
- import org.ourpioneer.course.bean.Course;
- import org.ourpioneer.course.dao.CourseDAO;
- import org.ourpioneer.course.dao.CourseDAOImpl;
- public class Demo {
- public static void main(String[] args) {
- CourseDAO courseDAO = new CourseDAOImpl();
- Course course = new Course();
- course.setTitle("Spring ORM");
- course.setStartDate(new GregorianCalendar(2011, 1, 1).getTime());
- course.setEndDate(new GregorianCalendar(2011, 2, 1).getTime());
- course.setFee(100);
- courseDAO.save(course);
- List courses = courseDAO.findAll();
- Long courseId = courses.get(0).getId();
- course = courseDAO.findById(courseId);
- System.out.println(course);
- courseDAO.delete(course);
- }
- }
首先創(chuàng)建的是Course對象,并設置其中的屬性,使用save方法將其持久化到數(shù)據(jù)庫中,之后通過findAll方法查詢數(shù)據(jù)庫中的全部記錄,當然現(xiàn)在只有一條。并拿到Id,在通過findById方法獲取出來,然后打印結(jié)果。最終刪除記錄。執(zhí)行該程序,我們可以得到如下輸出信息:
我們之前并沒有在數(shù)據(jù)庫中建表,而Hibernate在執(zhí)行插入之前會為我們自動建表,然后執(zhí)行插入操作,兩次查詢操作,并打印出對象信息,最后執(zhí)行了刪除操作,從SQL語句中可以看到Hibernate最終的執(zhí)行結(jié)果是什么。而此時回到數(shù)據(jù)庫中,會發(fā)現(xiàn)一個建好的表。
Hibernate的簡單ORM映射操作就介紹完了,下面來看使用JPA注解和Hibernate的API來持久化對象,首先修改持久化類:
- package org.ourpioneer.course.bean;
- import java.sql.Date;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- /**
- * 課程信息描述bean
- *
- * @author Nanlei
- *
- */
- @Entity
- @Table(name = "course")
- public class Course {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID")
- private Long id;
- @Column(name = "TITLE", length = 100, nullable = false)
- private String title;
- @Column(name = "STARTDATE",nullable=false)
- private java.util.Date startDate;
- @Column(name = "ENDDATE",nullable=false)
- private java.util.Date endDate;
- @Column(name = "FEE",nullable=false)
- private int fee;
- // 其余內(nèi)容不變,省略
- }
使用JPA的注解,首先對類進行注解,使用@Entity,并關聯(lián)數(shù)據(jù)庫表,使用@Table。下面就是對字段進行主鍵了,標識符(主鍵)字段要使用@Id,還要指定生成策略和對應的列名,剩下的字段只需指定列信息即可?,F(xiàn)在告訴Hibernate我們使用JPA注解,而不使用映射文件了,如下配置:
修改DAO實現(xiàn)類的構(gòu)造方法,使用注解配置方式創(chuàng)建SessionFactory,如下即可:
- public CourseDAOImpl() {
- // Configuration cfg = new Configuration().configure();
- Configuration cfg = new AnnotationConfiguration().configure();
- sessionFactory = cfg.buildSessionFactory();
- }
此時再次執(zhí)行測試方法,反饋的信息沒有任何變化,但是我們就使用了JPA注解而并非Hibernate的映射信息了。下面來看看使用Hibernate作為JPA引擎的持久化步驟。先配置依賴,引入:
org.hibernate groupId> hibernate-entitymanager artifactId> 3.6.0.Final version> jar type> compile scope> - dependency>
jboss groupId> jboss-archive-browsing artifactId> 5.0.0alpha-200607201-119 version> jar type> compile scope> - dependency>
如果在Java EE容器中運行JPA,可以通過容器來配置JPA,如果是在Java SE中運行JPA,那么需要在類路徑的META-INF下配置persistence.xml來配置持久化單元,在本例中我們使用Hibernate作為JPA的引擎,就可以這么來寫:
- '1.0' encoding='UTF-8'?>
- "http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
- http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
- "course">
- "hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />
加載配置文件仍然使用Hibernate的配置文件,或者也可以將其中的property寫在persistence.xml中,那么因為在這里JPA已經(jīng)可以獲取持久化單元了,在Hibernate的配置中就需要配置持久化對象的映射了,去掉mapping信息即可。有了配置信息,還需要實現(xiàn)類,我們重寫一個JPA的DAO實現(xiàn),如下:
Java代碼
- package org.ourpioneer.course.dao;
- import java.util.List;
- import javax.persistence.EntityManager;
- import javax.persistence.EntityManagerFactory;
- import javax.persistence.EntityTransaction;
- import javax.persistence.Persistence;
- import javax.persistence.Query;
- import org.ourpioneer.course.bean.Course;
- public class CourseDAOImplJPA implements CourseDAO {
- private EntityManagerFactory entityManagerFactory;
- public CourseDAOImplJPA() {
- entityManagerFactory = Persistence.createEntityManagerFactory("course");
- }
- public void delete(Course course) {
- EntityManager manager = entityManagerFactory.createEntityManager();
- EntityTransaction tx = manager.getTransaction();
- try {
- tx.begin();
- manager.remove(manager.merge(course));
- tx.commit();
- } catch (RuntimeException e) {
- tx.rollback();
- throw e;
- } finally {
- manager.close();
- }
- }
- public List findAll() {
- EntityManager manager = entityManagerFactory.createEntityManager();
- try {
- Query query = manager
- .createQuery("select course from Course course");
- return query.getResultList();
- } finally {
- manager.close();
- }
- }
- public Course findById(Long courseId) {
- EntityManager manager = entityManagerFactory.createEntityManager();
- try {
- return manager.find(Course.class, courseId);
- } finally {
- manager.close();
- }
- }
- public void save(Course course) {
- EntityManager manager = entityManagerFactory.createEntityManager();
- EntityTransaction tx = manager.getTransaction();
- try {
- tx.begin();
- manager.persist(course);
- tx.commit();
- } catch (RuntimeException e) {
- tx.rollback();
- throw e;
- } finally {
- manager.close();
- }
- }
- public void update(Course course) {
- EntityManager manager = entityManagerFactory.createEntityManager();
- EntityTransaction tx = manager.getTransaction();
- try {
- tx.begin();
- manager.merge(course);
- tx.commit();
- } catch (RuntimeException e) {
- tx.rollback();
- throw e;
- } finally {
- manager.close();
- }
- }
- }
這里特別要注意的是delete方法,首先調(diào)用merge方法,否則當前對象是出于脫管態(tài)的,無法和Session進行關聯(lián),也就無法刪除該對象。不加merge方法時候會拋出異常,大家可以測試一下,因為底層還是Hibernate進行的,Hibernate的持久化對象有三種狀態(tài),那么就要注意狀態(tài)發(fā)生的變化。
#p#
現(xiàn)在我們來看如何在Spring中配置ORM資源工廠,也就是在Spring中使用ORM框架。仍然以Hibernate為例來說明,要引入spring-orm和spring-context模塊來做測試。首先我們可以修改一下DAO實現(xiàn)類的寫法,因為用了Spring,就不用顯式來new對象了,那么對于Hibernate的SessionFactory,使用注入的方式來進行配置,修改CourseDAOImpl類,如下設置:
- private SessionFactory sessionFactory;
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.sessionFactory = sessionFactory;
- }
去掉構(gòu)造方法,為sessionFactory提供get方法即可。之后就是配置Spring了,很簡單,要配置courseDao和sessionFactory:
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- bean>
property> - bean>
把Hibernate配置對象的映射文件加上,之后修改測試方法,從Spring的容器中獲取對象就可以了:
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- "classpath:applicationContext.xml");
- CourseDAO courseDAO = (CourseDAO) ctx.getBean("courseDao");
此時,我們還依賴Hibernate的配置文件,那么完全可以把Hibernate中的配置信息移入Spring之中,因為Spring的ORM模塊完全支持Hibernate,可以如下進行,我們使用C3P0作為連接池:
- scope="singleton" destroy-method="close">
- bean>
將數(shù)據(jù)庫的基本信息配置好后,數(shù)據(jù)源的配置就完成了。下面是配置Hibernate:
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- value="classpath:org/ourpioneer/course/hbm/*.hbm.xml" />
org.hibernate.dialect.MySQLDialect prop> true prop> update prop> - props>
- property>
- bean>
這里我們將實體映射一起配置進來,使用了*通配符,并配置了基本的Hibernate屬性,比如方言,顯示sql語句和自動建表。剩下的就是DAO的配置了,它不用做什么修改,仍然注入sessionFactory即可,然后執(zhí)行測試:
從中可以看到啟動信息和Hibernate生成的SQL語句。除了使用Hibernate的實體映射文件外,我們還可以使用注解,之前已經(jīng)在Course持久化類中添加了注解,那么我們就來配置使用注解的方式,很簡單,只需修改Spring中的Hibernate SessionFactory配置即可,如下:
- class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
org.ourpioneer.course.bean.Course value> - list>
- property>
org.hibernate.dialect.MySQLDialect prop> true prop> update prop> - props>
- property>
- bean>
這樣就使用在持久化類中的注解信息而不需要單獨編寫HBM映射文件了,執(zhí)行測試,結(jié)果是一樣的。當然,在Spring中,還可以使用JPA的EntityManager來進行數(shù)據(jù)的持久化操作,那么又如何來進行呢?和前面介紹的類似,首先在JPA的DAO實現(xiàn)類中修改EntityManager的配置方式,使用注入來進行:
- private EntityManagerFactory entityManagerFactory;
- public void setEntityManagerFactory(
- EntityManagerFactory entityManagerFactory) {
- this.entityManagerFactory = entityManagerFactory;
- }
同理,修改Spring的配置文件,配置EntityManagerFactory,如下:
- class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
- bean>
因為配置了persistenceUnitName,那么不要忘記了在META-INF目錄下的persistence.xml文件,其中是這么寫的:
本文題目:Spring數(shù)據(jù)庫訪問之ORM
- properties>
- persistence-unit>
分享路徑:http://fisionsoft.com.cn/article/cogsdch.html


咨詢
建站咨詢
