1. 程式人生 > >Spring實戰——使用物件-關係對映持久化資料

Spring實戰——使用物件-關係對映持久化資料

一、在Spring中整合hibernate

1、hibernate簡介:

      hibernate是目前很流行的開源持久化框架。不僅提供了基本的物件關係對映,還提供了ORM工具所應具有的所有複雜功能,比如快取、延遲載入、預先抓取以及分散式快取。

2、宣告hibernate的Session工廠

在Spring中,需要通過Spring的某一個Hibernate Session工廠bean來獲取Hibernate SessionFactory。從3.1版本開始,Spring提供了三個Session工廠的Bean:

org.springframework.orm.hibernate3.LocalSessionFactoryBean

org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean

org.springframework.orm.hibernate4.LocalSessionFactoryBean

對於以上三個Session工廠,選擇方式如下:

①如果使用hibernate版本在3.2或更高版本(知道hibernate4.0,但不包含4.0),並且使用XML定義對映的話,就使用org.springframework.orm.hibernate3包中的LocalSessionFactoryBean。

②如果使用hibernate版本在3.2或更高版本(知道hibernate4.0,但不包含4.0),並且使用註解定義對映的話,就使用org.springframework.orm.hibernate3.annotation包中的AnnotationSessionFactoryBean。

③如果使用hibernate4,就使用org.springframework.orm.hibernate4.LocalSessionFactoryBean,這個Session工廠既可以匹配XML對映,也可以匹配註解對映。

3、在Spring中整合Hibernate的配置

先在web.xml中新增配置:

    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
	

然後在Spring-dao.xml中配置SessionFactory(這裡實體類使用註解對映):

	<!-- 資料來源連線池配置三種方式(推薦使用):DBCP、C3P0、BoneCP -->
	<!-- DBCP配置資料來源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
		<property name="username" value="scott"></property>
		<property name="password" value="scott"></property>
	</bean>
	
	<!-- 配置sessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="packagesToScan" value="com.mfc.entity"></property>
		<property name="hibernateProperties">
			<props>
                <prop key="hibernate.show_sql">true</prop>     <!--在控制檯顯示執行的資料庫操作語句-->
                <prop key="hibernate.format_sql">true</prop>     <!--在控制檯顯示執行的資料哭操作語句(格式)-->
                <prop key="hibernate.connection.autocommit">true</prop>
			</props>
		</property>
	</bean>

使用Java配置SessionFactory:

	@Bean
	public LocalSessionFactoryBean sessionFactory(DataSource dataSource){
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource);
		sessionFactory.setPackagesToScan(new String[]{"com.mfc.entity"});
		Properties properties = new Properties();
		properties.setProperty("hibernate.show_sql", "true");
		properties.setProperty("hibernate.format_sql", "true");
		properties.setProperty("hibernate.connection.autocommit", "true");
		return sessionFactory;
	}

4、在dao層中使用SessionFactory:

以前經常使用HibernateTemplate,HibernateTemplate能夠保證每個事務使用同一個Session,但是這種方式的弊端在於Repository實現會直接與Spring耦合。

先在的最佳實現是使用上下文Session,通過這種方式,會直接將Hibernate的SessionFactory裝配到Repository中,並使用它來獲取Session,程式如下:

package com.mfc.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.mfc.entity.Tuser;

@Repository(value = "tuserDao")
public class TuserDaoImpl implements TuserDao {
	
	@Autowired
	private SessionFactory sessionFactory;
	
	private Session getSession(){
		return sessionFactory.getCurrentSession();
	}
	
	@Override
	public void add(Tuser tuser) {
		getSession().save(tuser);
	}

	@Override
	public void delete(Tuser tuser) {
		getSession().delete(tuser);
	}

	@Override
	public void update(Tuser tuser) {
		getSession().update(tuser);
	}

	@Override
	public List<Tuser> find(Tuser tuser) {
		return getSession().createCriteria(Tuser.class).list();
	}

	@Override
	public Tuser findByPrimary(String userId) {
		return (Tuser) getSession().get(Tuser.class, userId);
	}
}

二、Spring與Java持久化API

1、實體管理器工廠介紹

   基於JPA的應用程式需要使用EntityManagerFactory的實現類來獲取EntityManager例項。JPA定義了兩種型別的實體管理器。

①應用程式管理型別:這種適用於不執行在Java EE容器中的獨立應用程式,不做介紹

②容器管理型別:由JavaEE建立和管理,下面主要看這個。org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean

2、使用容器管理型別的JPA

①在Spring容器中注入LocalContainerEntityManagerFactoryBean

	<!-- DBCP配置資料來源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
		<property name="username" value="scott"></property>
		<property name="password" value="scott"></property>
	</bean>
	
	<bean id="em" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
		<property name="packagesToScan" value="com.mfc.entity"></property>
	</bean>
	<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="database" value="ORACLE"></property>
		<property name="showSql" value="true"></property>
		<property name="generateDdl" value="false"></property>
	</bean>
	
	

②使用Java配置代替上面的配置:

	@Bean
	public BasicDataSource dataSource(){
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("");
		dataSource.setUrl("");
		dataSource.setUsername("");
		dataSource.setPassword("");
		return dataSource;
	}
	
	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
		LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
		em.setDataSource(dataSource);
		em.setJpaVendorAdapter(jpaVendorAdapter);
		em.setPackagesToScan(new String[]{"com.mfc.entity"});
		return em;
	}
	
	@Bean
	public JpaVendorAdapter jpaVendorAdapter(){
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		jpaVendorAdapter.setDatabase("ORACLE");
		jpaVendorAdapter.setShowSql(true);
		jpaVendorAdapter.setGenerateDdl(false);
		return jpaVendorAdapter;
	}

③上面程式碼中的jpaVendorAdapter屬性用於指明哪一個廠商的JPA實現,Spring提供了多個JPA廠商介面卡:

EclipseLinkJpaVendorAdapter、HibernateJpaVendorAdapter、OpenJpaVendorAdapter、TopLinkJpaVendorAdapter(已廢棄)

④上面配置中,注入HibernateJpaVendorAdapter時最終啊喲的是database屬性,對應不同資料庫,database屬性的值不同。

Hibernate的JPA介面卡支援多種資料庫,可以通過database的屬性配置使用哪個資料庫
資料庫平臺 屬性database的值
IBM DB2 DB2
Apache Derby DERBY
H2 H2
Hypersonic HSQL
Informix INFORMIX
MySql MYSQL
oracle ORACLE
PostgresQL POSTGRESQL
Microsoft SQL Server SQL SERVER
Sybase SYBASE

3、從JNDI獲取實體管理器工廠

xml配置:

	<jee:jndi-lookup jndi-name="OracleConnection" id="emf"></jee:jndi-lookup>
	
	<bean id="em" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName" value="emf"></property>
	</bean>

Java配置:

    @Bean
	public JndiObjectFactoryBean dataSource(){
		JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
		factoryBean.setJndiName("OracleConnection");
		factoryBean.setProxyInterface(DataSource.class);
		return factoryBean;
	}
    
    @Bean
    public JndiObjectFactoryBean entityManagerFactory(){
    	JndiObjectFactoryBean em = new JndiObjectFactoryBean();
    	em.setJndiName("OracleConnection");
    	return em;
    }

4、使用JPA編寫Dao:

package com.mfc.dao;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import org.springframework.stereotype.Repository;

import com.mfc.entity.Tuser;

@Repository(value = "jpaTuserDao")
@Transactional
public class JPATuserDaoImpl implements TuserDao {
	
	@PersistenceContext
	private EntityManager em;

	@Override
	public void add(Tuser tuser) {
		em.persist(tuser);

	}

	@Override
	public void delete(Tuser tuser) {
		em.remove(em.merge(tuser));
	}

	@Override
	public void update(Tuser tuser) {
		em.persist(em.merge(tuser));
	}

	@Override
	public List<Tuser> find(Tuser tuser) {
		String queryString = "select * from tuser";
	    Query query = em.createNativeQuery(queryString,Tuser.class);
	    List<?> result = query.getResultList();
	    List<Tuser> users = new ArrayList<Tuser>();
	    if (result !=null) {
           Iterator<?> iterator =result.iterator();
           while (iterator.hasNext()) {
              Tuser user = (Tuser)iterator.next();
              users.add(user);
           }
        }
	    return users;
	}

	@Override
	public Tuser findByPrimary(String userId) {
		return em.find(Tuser.class, userId);
	}

}

三、藉助SpringData實現自動化的JPA Repository

參考:https://blog.csdn.net/itguangit/article/details/78748077

           https://blog.csdn.net/wu920604/article/details/52595999

以下值記錄了Maven依賴和Spring注入配置,其他具體操作和介紹可以看上面參考的兩篇部落格。

1、這裡注意Spring和Spring Data JPA的版本,我使用的Maven依賴:

  <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <spring.version>4.3.10.RELEASE</spring.version>
  </properties>
  <dependencies>

	 <!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
	<dependency>
	    <groupId>commons-dbcp</groupId>
	    <artifactId>commons-dbcp</artifactId>
	    <version>1.4</version>
	</dependency>
	
    <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc14 -->
	<dependency>
	    <groupId>com.oracle</groupId>
	    <artifactId>ojdbc14</artifactId>
	    <version>10.2.0.1.0</version>
	</dependency>  
	
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
          <!-- springframework 4 dependencies begin -->
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
       <!--  https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aspects</artifactId>
		    <version>${spring.version}</version>
		</dependency>
		
		<!-- spring data jpa 資料庫持久層 -->
         <dependency>
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-jpa</artifactId>
             <version>1.10.4.RELEASE</version>
         </dependency>
        
        <!-- springframework 4 dependencies end -->
        
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-validator</artifactId>
		    <version>4.3.1.Final</version>
		</dependency>
		
		<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.11.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.11.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.0-api -->
		<dependency>
		    <groupId>org.hibernate.javax.persistence</groupId>
		    <artifactId>hibernate-jpa-2.0-api</artifactId>
		    <version>1.0.1.Final</version>
		</dependency>
        
  </dependencies>
  <build>
    <finalName>SpringInAction7</finalName>
  </build>
</project>

2、Spring-dao.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- DBCP配置資料來源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
		<property name="username" value="scott"></property>
		<property name="password" value="scott"></property>
	</bean>
	
	<!-- 使用JPA實現持久化配置 -->
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
		<property name="packagesToScan" value="com.mfc.entity"></property>
	</bean>
	<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="database" value="ORACLE"></property>
		<property name="showSql" value="true"></property>
		<property name="generateDdl" value="false"></property>
	</bean> 
	
	<!-- 配置事務管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
	
	<!-- 測試:使用Spring Data構建自動化的JPA Repository ,com.mfc.SpringDataJPA是Repository介面的包名-->
	<jpa:repositories base-package="com.mfc.SpringDataJPA"></jpa:repositories>
</beans>