溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring數據庫訪問之ORM的示例分析

發布時間:2021-12-09 13:47:48 來源:億速云 閱讀:161 作者:小新 欄目:編程語言

這篇文章主要介紹Spring數據庫訪問之ORM的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

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

首先我們從單獨使用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;       //必須提供無參默認構造方法       public Course() {           super();       }       //省略其它構造方法,getter和setter等方法


作為對數據訪問的一種模式,我們仍然應用DAO模式,寫DAO類已經很熟練了,如下設計即可:

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操作,那么實現類中我們用Hibernate幫助我們進行數據庫訪問操作也非常簡單:

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();             }         }     }

這里只展示幾個方法作為代表,其它方法類似可以寫出,非常簡單。首先是構造方法,初始化實現類時創建Hibernate的配置對象,new Configuration().configure()時,Hibernate會在類路徑的根路徑下自動尋找名為hibernate.cfg.xml的配置文件并加載,之后就是創建Hibernate的Session對象,利用Session對象提供和衍生出的方法來進行數據庫操作。下面來看配置文件,這是比較重要的,因為通過配置文件,把數據庫信息和實體Bean的信息都告訴Hibernate,可以省去我們很多在數據庫設計上的事情。

<?xml version='1.0' encoding='UTF-8'?>              "-//Hibernate/Hibernate Configuration DTD 3.0//EN"       "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">    <hibernate-configuration>        <session-factory>            <property name="connection.driver_class">com.mysql.jdbc.Driverproperty>            <property name="connection.url">jdbc:mysql:///testproperty>            <property name="connection.username">rootproperty>            <property name="connection.password">123property>            <property name="dialect">org.hibernate.dialect.MySQLDialectproperty>            <property name="show_sql">trueproperty>            <property name="hbm2ddl.auto">updateproperty>            <mapping resource="org/ourpioneer/course/hbm/course.hbm.xml" />        session-factory>    hibernate-configuration>

這里我們告訴Hibernate使用mysql數據庫,并配置數據庫信息,所用方言,并在執行應用程序時在控制臺打印出還原的SQL語句。使用hbm2ddl.auto可以讓Hibernate根據實體Bean的配置信息來自動建表,這是很方便的,最后的mapping就是配置實體bean映射信息的文件,我們來看一下:

<?xml version="1.0" encoding="UTF-8"?>    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">    <hibernate-mapping package="org.ourpioneer.course.bean">        <class name="Course" table="course">            <id name="id" type="java.lang.Long" column="ID">                <generator class="identity" />            id>            <property name="title" type="java.lang.String" column="TITLE"                length="100" not-null="true" />            <property name="startDate" type="java.sql.Date" column="STARTDATE"                not-null="true" />            <property name="endDate" type="java.sql.Date" column="ENDDATE"                not-null="true" />            <property name="fee" type="java.lang.Integer" column="FEE"                not-null="true" />        class>    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中配置一下這個地址:

<repositories>        <repository>            <releases>                <updatePolicy>alwaysupdatePolicy>            releases>            <snapshots>                <updatePolicy>alwaysupdatePolicy>            snapshots>            <id>Jbossid>            <name>Jboss Repositoryname>    <url>https://repository.jboss.org/nexus/content/groups/publicurl>        repository>    repositories>

之后,為項目引入其它必要的依賴,使用Maven管理,我們不需自己再去尋找各種依賴了,非常簡單的管理,如圖所示:

Spring數據庫訪問之ORM的示例分析

下面來看示例程序:

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);         }     }

首先創建的是Course對象,并設置其中的屬性,使用save方法將其持久化到數據庫中,之后通過findAll方法查詢數據庫中的全部記錄,當然現在只有一條。并拿到Id,在通過findById方法獲取出來,然后打印結果。最終刪除記錄。執行該程序,我們可以得到如下輸出信息:

Spring數據庫訪問之ORM的示例分析

我們之前并沒有在數據庫中建表,而Hibernate在執行插入之前會為我們自動建表,然后執行插入操作,兩次查詢操作,并打印出對象信息,最后執行了刪除操作,從SQL語句中可以看到Hibernate最終的執行結果是什么。而此時回到數據庫中,會發現一個建好的表。

Spring數據庫訪問之ORM的示例分析

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;         // 其余內容不變,省略     }

使用JPA的注解,首先對類進行注解,使用@Entity,并關聯數據庫表,使用@Table。下面就是對字段進行主鍵了,標識符(主鍵)字段要使用@Id,還要指定生成策略和對應的列名,剩下的字段只需指定列信息即可?,F在告訴Hibernate我們使用JPA注解,而不使用映射文件了,如下配置:

    <mapping class="org.ourpioneer.course.bean.Course"/>

修改DAO實現類的構造方法,使用注解配置方式創建SessionFactory,如下即可:

public CourseDAOImpl() {         // Configuration cfg = new Configuration().configure();         Configuration cfg = new AnnotationConfiguration().configure();         sessionFactory = cfg.buildSessionFactory();     }

此時再次執行測試方法,反饋的信息沒有任何變化,但是我們就使用了JPA注解而并非Hibernate的映射信息了。下面來看看使用Hibernate作為JPA引擎的持久化步驟。先配置依賴,引入:

<dependency>        <groupId>org.hibernategroupId>        <artifactId>hibernate-entitymanagerartifactId>        <version>3.6.0.Finalversion>        <type>jartype>        <scope>compilescope>    dependency>    <dependency>        <groupId>jbossgroupId>        <artifactId>jboss-archive-browsingartifactId>        <version>5.0.0alpha-200607201-119version>        <type>jartype>        <scope>compilescope>    dependency>

如果在Java EE容器中運行JPA,可以通過容器來配置JPA,如果是在Java SE中運行JPA,那么需要在類路徑的META-INF下配置persistence.xml來配置持久化單元,在本例中我們使用Hibernate作為JPA的引擎,就可以這么來寫:

<?xml version='1.0' encoding='UTF-8'?>    <PERSISTENCE XMLNS=< span>"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">        <PERSISTENCE-UNIT NAME=< span>"course">                            <PROPERTY NAME=< span>"hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />

加載配置文件仍然使用Hibernate的配置文件,或者也可以將其中的property寫在persistence.xml中,那么因為在這里JPA已經可以獲取持久化單元了,在Hibernate的配置中就需要配置持久化對象的映射了,去掉mapping信息即可。有了配置信息,還需要實現類,我們重寫一個JPA的DAO實現,如下:

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方法,首先調用merge方法,否則當前對象是出于脫管態的,無法和Session進行關聯,也就無法刪除該對象。不加merge方法時候會拋出異常,大家可以測試一下,因為底層還是Hibernate進行的,Hibernate的持久化對象有三種狀態,那么就要注意狀態發生的變化。

現在我們來看如何在Spring中配置ORM資源工廠,也就是在Spring中使用ORM框架。仍然以Hibernate為例來說明,要引入spring-orm和spring-context模塊來做測試。首先我們可以修改一下DAO實現類的寫法,因為用了Spring,就不用顯式來new對象了,那么對于Hibernate的SessionFactory,使用注入的方式來進行配置,修改CourseDAOImpl類,如下設置:

private SessionFactory sessionFactory;     public void setSessionFactory(SessionFactory sessionFactory) {         this.sessionFactory = sessionFactory;     }

去掉構造方法,為sessionFactory提供get方法即可。之后就是配置Spring了,很簡單,要配置courseDao和sessionFactory:

<bean id="sessionFactory"    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">        <property name="configLocation" value="classpath:hibernate.cfg.xml" />    bean>    <bean id="courseDao" class="org.ourpioneer.course.dao.CourseDAOImpl">        <property name="sessionFactory" ref="sessionFactory">property>    bean>

把Hibernate配置對象的映射文件加上,之后修改測試方法,從Spring的容器中獲取對象就可以了:

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

此時,我們還依賴Hibernate的配置文件,那么完全可以把Hibernate中的配置信息移入Spring之中,因為Spring的ORM模塊完全支持Hibernate,可以如下進行,我們使用C3P0作為連接池:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"        scope="singleton" destroy-method="close">        <property name="driverClass" value="com.mysql.jdbc.Driver" />        <property name="jdbcUrl" value="jdbc:mysql:///test" />        <property name="user" value="root" />        <property name="password" value="123" />    bean>

將數據庫的基本信息配置好后,數據源的配置就完成了。下面是配置Hibernate:

<bean id="sessionFactory"    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">        <property name="dataSource" ref="dataSource" />        <property name="mappingLocations"            value="classpath:org/ourpioneer/course/hbm/*.hbm.xml" />        <property name="hibernateProperties">            <props>                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialectprop>                <prop key="hibernate.show_sql">trueprop>                <prop key="hibernate.hbm2ddl.auto">updateprop>            props>        property>    bean>

這里我們將實體映射一起配置進來,使用了*通配符,并配置了基本的Hibernate屬性,比如方言,顯示sql語句和自動建表。剩下的就是DAO的配置了,它不用做什么修改,仍然注入sessionFactory即可,然后執行測試:

Spring數據庫訪問之ORM的示例分析

從中可以看到啟動信息和Hibernate生成的SQL語句。除了使用Hibernate的實體映射文件外,我們還可以使用注解,之前已經在Course持久化類中添加了注解,那么我們就來配置使用注解的方式,很簡單,只需修改Spring中的Hibernate SessionFactory配置即可,如下:

<bean id="sessionFactory"    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">        <property name="dataSource" ref="dataSource" />        <property name="annotatedClasses">            <list>                <value>org.ourpioneer.course.bean.Coursevalue>            list>        property>        <property name="hibernateProperties">            <props>                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialectprop>                <prop key="hibernate.show_sql">trueprop>                <prop key="hibernate.hbm2ddl.auto">updateprop>            props>        property>    bean>

這樣就使用在持久化類中的注解信息而不需要單獨編寫HBM映射文件了,執行測試,結果是一樣的。當然,在Spring中,還可以使用JPA的EntityManager來進行數據的持久化操作,那么又如何來進行呢?和前面介紹的類似,首先在JPA的DAO實現類中修改EntityManager的配置方式,使用注入來進行:

private EntityManagerFactory entityManagerFactory;     public void setEntityManagerFactory(             EntityManagerFactory entityManagerFactory) {         this.entityManagerFactory = entityManagerFactory;     }

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

<bean id="entityManagerFactory"    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">        <property name="persistenceUnitName" value="course" />    bean>

因為配置了persistenceUnitName,那么不要忘記了在META-INF目錄下的persistence.xml文件,其中是這么寫的:

<persistence-unit name="course">        <properties>            <property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />        properties>    persistence-unit>

因為還用到了hibernate.cfg.xml,不過要將mapping的映射信息全部去掉,之后的courseDaoJPA配置就很簡單了:

<bean id="courseDaoJPA" class="org.ourpioneer.course.dao.CourseDAOImplJPA">        <property name="entityManagerFactory" ref="entityManagerFactory" />    bean>

在測試程序的ctx.getBean方法中換成courseDaoJPA就可以獲得JPA的DAO實現對象了,從而進行數據庫操作,這也非常簡單。如果不使用hibernate的配置文件,那么需要對JPA進行如下的配置:

<bean id="entityManagerFactory"    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">        <property name="persistenceUnitName" value="course" />        <property name="dataSource" ref="dataSource" />        <property name="jpaVendorAdapter">            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />                <property name="showSql" value="true" />                <property name="generateDdl" value="true" />            bean>        property>    bean>

將數據源注入進來,并配置一些數據庫方言,顯示sql和生成ddl的信息,最后精簡一下persistence.xml文件中的內容:

<persistence-unit name="course" />

已經不需要再使用Hibernate的配置文件了,這樣就可以了,再次執行測試程序,就可以得到如下輸出信息:

Spring數據庫訪問之ORM的示例分析

在JDBC模塊中,Spring的JDBC模板簡化了SQL的操作,使得使用SQL非常簡便,不需要很多的代碼就能完成數據庫操作,同樣,在ORM模塊中,Spring的模板技術也有應用,這里我們主要來看Hibernate模板和JPA模板技術。使用HibernateTemplate非常簡單,在DAO的實現類中進行注入即可,使用Hibernate模板為我們提供的方法來執行ORM操作,非常的簡便:

package org.ourpioneer.course.dao;     import java.util.List;     import org.ourpioneer.course.bean.Course;     import org.springframework.orm.hibernate3.HibernateTemplate;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplHibernate implements CourseDAO {         private HibernateTemplate hibernateTemplate;         public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {             this.hibernateTemplate = hibernateTemplate;         }         @Transactional        public void delete(Course course) {             hibernateTemplate.delete(course);         }         @Transactional(readOnly = true)         public List findAll() {             return hibernateTemplate.find("from Course");         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return (Course) hibernateTemplate.get(Course.class, courseId);         }         @Transactional        public void save(Course course) {             hibernateTemplate.save(course);         }         @Transactional        public void update(Course course) {             hibernateTemplate.update(course);         }     }

其中使用了注解進行事務說明,就不用寫在配置文件中了,編寫好代碼,要讓Spring容器知道我們的做法,進行如下配置:

<tx:annotation-driven />        <bean id="transactionManager"        class="org.springframework.orm.hibernate3.HibernateTransactionManager">            <property name="sessionFactory" ref="sessionFactory" />        bean>        <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">            <property name="sessionFactory" ref="sessionFactory" />        bean>        <bean id="courseDaoHibernate" class="org.ourpioneer.course.dao.CourseDAOImplHibernate">            <property name="hibernateTemplate" ref="hibernateTemplate" />        bean>

使用tx前綴,只需加上相應的命名空間說明即可,這也很簡單。修改主程序:

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.springframework.context.ApplicationContext;     import org.springframework.context.support.ClassPathXmlApplicationContext;     public class Demo {         public static void main(String[] args) {             ApplicationContext ctx = new ClassPathXmlApplicationContext(                     "classpath:applicationContext.xml");             CourseDAO courseDAO = (CourseDAO) ctx.getBean("courseDaoHibernate");             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);         }     }

運行主程序,就可以看到執行效果了:

Spring數據庫訪問之ORM的示例分析

相對于HibernateTemplate,JpaTemplate也可以實現相同功能,我們來看如下代碼:

package org.ourpioneer.course.dao;     import java.util.List;     import org.ourpioneer.course.bean.Course;     import org.springframework.orm.jpa.JpaTemplate;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplJPA implements CourseDAO {         private JpaTemplate jpaTemplate;         public void setJpaTemplate(JpaTemplate jpaTemplate) {             this.jpaTemplate = jpaTemplate;         }         @Transactional        public void delete(Course course) {             jpaTemplate.remove(jpaTemplate.merge(course));         }         @Transactional(readOnly = true)         public List findAll() {             return jpaTemplate.find("from Course");         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return jpaTemplate.find(Course.class, courseId);         }         @Transactional        public void save(Course course) {             jpaTemplate.merge(course);         }         @Transactional        public void update(Course course) {             jpaTemplate.merge(course);         }     }

這里不能忘了delete方法需要首先將脫管態的對象變為持久態的才能進行操作,否則就會發生異常。同樣,對于配置文件,也要做響應的調整:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">        <property name="entityManagerFactory" ref="entityManagerFactory" />    bean>    <bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">        <property name="entityManagerFactory" ref="entityManagerFactory" />    bean>    <bean id="courseDaoJPA" class="org.ourpioneer.course.dao.CourseDAOImplJPA">        <property name="jpaTemplate" ref="jpaTemplate" />    bean>

這樣,我們修改測試程序中getBean獲得的對象,就可以測試程序了,這都非常簡單了。這里我們擴展說一點,使用了HibernateTemplate或jpaTemplate后,如果想獲取Session或EntityManager,那么可以這么操作:hibernateTemplate.getSessionFactory().getCurrentSession(),對于JPA則是:jpaTemplate.getEntityManager(),除此之外,我們還可以使用他們的execute()方法來執行操作:

hibernateTemplate.execute(new HibernateCallback() {             public Object doInHibernate(Session session) throws HibernateException,SQLException {             }         };

JPA的則是:

jpaTemplate.execute(new JpaCallback() {         public Object doInJpa(EntityManager em) throws PersistenceException {         return null;         }     });

以上我們是在DAO實現類中直接注入模板來進行操作的,當然我們還可以讓實現類繼承各自的DaoSupport類來獲得模板進行操作,這很簡單,我們來看:

package org.ourpioneer.course.dao;     import java.util.List;     import org.ourpioneer.course.bean.Course;     import org.springframework.orm.hibernate3.support.HibernateDaoSupport;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplHibernate extends HibernateDaoSupport implements            CourseDAO {         @Transactional        public void delete(Course course) {             getHibernateTemplate().delete(course);         }         @Transactional(readOnly = true)         public List findAll() {             return getHibernateTemplate().find("from Course");         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return (Course) getHibernateTemplate().get(Course.class, courseId);         }         @Transactional        public void save(Course course) {             getHibernateTemplate().save(course);         }         @Transactional        public void update(Course course) {             getHibernateTemplate().update(course);         }     }

同時修改配置文件:

<bean id="courseDaoHibernate" class="org.ourpioneer.course.dao.CourseDAOImplHibernate">        <property name="sessionFactory" ref="sessionFactory" />    bean>

當然,也可以給該類注入HibernateTemplate,看一下該類的源碼即可參照使用對應的實例進行注入了,這都很簡單,JPA的修改也是相似的:

package org.ourpioneer.course.dao;     import java.util.List;     import org.ourpioneer.course.bean.Course;     import org.springframework.orm.jpa.support.JpaDaoSupport;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplJPA extends JpaDaoSupport implements CourseDAO {         @Transactional        public void delete(Course course) {             getJpaTemplate().remove(getJpaTemplate().merge(course));         }         @Transactional(readOnly = true)         public List findAll() {             return getJpaTemplate().find("from Course");         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return getJpaTemplate().find(Course.class, courseId);         }         @Transactional        public void save(Course course) {             getJpaTemplate().merge(course);         }         @Transactional        public void update(Course course) {             getJpaTemplate().merge(course);         }     }

同時,將配置文件修改為:

<bean id="courseDaoJPA" class="org.ourpioneer.course.dao.CourseDAOImplJPA">        <property name="entityManagerFactory" ref="entityManagerFactory" />    bean>

之前我們使用的是HibernateTemplate來進行對象的持久化的,其實在DAO實現類中我們還可以使用Hibernate的上下文Session來持久化對象。也就是通過SessionFactory對象的getCurrentSession()對象來獲得Session,然后通過Session來進行操作。
我們調整一下代碼:

package org.ourpioneer.course.dao;     import java.util.List;     import org.hibernate.Query;     import org.hibernate.SessionFactory;     import org.ourpioneer.course.bean.Course;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplHibernate implements CourseDAO {         private SessionFactory sessionFactory;         public void setSessionFactory(SessionFactory sessionFactory) {             this.sessionFactory = sessionFactory;         }         @Transactional        public void delete(Course course) {             sessionFactory.getCurrentSession().delete(course);         }         @Transactional(readOnly = true)         public List findAll() {             Query query = sessionFactory.getCurrentSession().createQuery(                     "from Course");             return query.list();         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return (Course) sessionFactory.getCurrentSession().get(Course.class,                     courseId);         }         @Transactional        public void save(Course course) {             sessionFactory.getCurrentSession().saveOrUpdate(course);         }         @Transactional        public void update(Course course) {             sessionFactory.getCurrentSession().update(course);         }     }

這里要注意的是所有DAO的方法必須是支持事務的,這可以通過添加Transactional注解來完成,就很簡單了,之前也有過介紹。這樣就能保證DAO中所有方法都可以在同一個Session,同一個事務內來執行,達到使用事務的效果。
將代碼修改完成后,就要來修改配置文件了:

<tx:annotation-driven />        <bean id="transactionManager"        class="org.springframework.orm.hibernate3.HibernateTransactionManager">            <property name="sessionFactory" ref="sessionFactory" />        bean>        <bean id="courseDaoHibernate" class="org.ourpioneer.course.dao.CourseDAOImplHibernate">            <property name="sessionFactory" ref="sessionFactory" />        bean>

這樣,基于上下文Session的持久化對象就配置完畢了,在示例程序中來執行,就會看到效果。修改測試程序如下:

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.springframework.context.ApplicationContext;     import org.springframework.context.support.ClassPathXmlApplicationContext;     public class Demo {         public static void main(String[] args) {             ApplicationContext ctx = new ClassPathXmlApplicationContext(                     "classpath:applicationContext.xml");             CourseDAO courseDAO = (CourseDAO) ctx.getBean("courseDaoHibernate");             Course course = new Course();             course.setTitle("Spring ORM");             course.setStartDate(new GregorianCalendar(2011, 2, 1).getTime());             course.setEndDate(new GregorianCalendar(2011, 3, 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);             course.setFee(200);             courseDAO.update(course);             System.out.println(course);             courseDAO.delete(course);         }     }

在控制臺,我們可以看到如下輸出:

Spring數據庫訪問之ORM的示例分析

這種方式和使用HibernateTemplate有的不同是它們對異常的處理。HibernateTemplate會將異常統一翻譯成Spring的數據訪問異常體系中的某個異常,而我們使用上下文的Session時,拋出的就不是Spring的異常,而是HibernateException,如果我們還想看到Spring的異常體系,就需要做點設置,當然這也很簡單。
在DAO實現類上加@Respository注解,并且注冊一個PersistenceExceptionTranslationPostProcessor實例即可。在Spring的配置文件中,我們加入如下內容:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">bean>

這是使用Hibernate的情況,那么使用JPA的情況和這個類似,我們來修改JPA的DAO實現類:

package org.ourpioneer.course.dao;     import java.util.List;     import javax.persistence.EntityManager;     import javax.persistence.PersistenceContext;     import javax.persistence.Query;     import org.ourpioneer.course.bean.Course;     import org.springframework.transaction.annotation.Transactional;     public class CourseDAOImplJPA implements CourseDAO {         @PersistenceContext        private EntityManager entityManager;         @Transactional        public void delete(Course course) {             entityManager.remove(entityManager.merge(course));         }         @Transactional(readOnly = true)         public List findAll() {             Query query = entityManager.createQuery("from Course");             return query.getResultList();         }         @Transactional(readOnly = true)         public Course findById(Long courseId) {             return entityManager.find(Course.class, courseId);         }         @Transactional        public void save(Course course) {             entityManager.merge(course);         }         @Transactional        public void update(Course course) {             entityManager.merge(course);         }     }

這里我們使用注解來聲明了EntityManager,那么需要在配置文件中在聲明一個PersistenceAnnotationBeanPostProcessor實例就好了。配置文件修改為:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">        <property name="entityManagerFactory" ref="entityManagerFactory" />    bean>    <bean id="courseDaoJPA" class="org.ourpioneer.course.dao.CourseDAOImplJPA" />    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">bean>

之后,將測試程序中的getBean()換成courseDaoJPA即可。
和HibernateTemplate一樣,JpaTemplate也會將異常翻譯為Spring的數據訪問異常,而如果改成entityManagerFactory之后,異常就會變成Java SE的異常,比如非法參數,非法狀態等異常。若要繼續使用Spring的異常體系,那么要為JPA的DAO實現類加上@Repository注解,然后注冊PersistenceExceptionTranslationPostProcessor實例。

以上是“Spring數據庫訪問之ORM的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女