Spring 配置jpa(轉)

http://www.cnblogs.com/liuyitian/p/4062748.html  原文地址css

 

前言:html

  JPA全稱Java Persistence API,即Java持久化API,它爲Java開發人員提供了一種對象/關係映射工具來管理Java應用中的關係數據,結合其餘ORM的使用,能達到簡化開發流程的目的,使開發者可以專一於實現本身的業務邏輯上。java

  Spring Jpa 可以簡化建立 JPA 數據訪問層和跨存儲的持久層功能,用戶的持久層Dao接口只須要繼承他本身定義好的(倉庫)接口,無需再寫實現類,就能夠實現對象的CRUD操做,還有分頁排序等功能。web

 


   寫本章以前原本想寫一個SpringMVC的,後來發現Jpa的配置能夠大大簡化MVC框架的配置,就先研究研究Spring Data Jpa。spring

準備工做:sql

  •  jar包支持(不用說都知道,本章jar包待我會放在115網盤供下載)
  •    web.xml配置(監聽Spring容器的裝載)
  •    本章採用的是阿里鏈接池(Druid),因此web.xml要有相關的配置
  •    Spring容器的配置(主要爲beans和jpa)
  •    Jpa的主要配置(實體類管理、數據源、鏈接池、事務等)
  •    實體類、持久層接口、業務層的建立
  •    測試放在下一章節中(由於採用了SpringJunit單元測試,單獨分出來說解)

 先來看一下本章節用到的包結構--以下圖:數據庫

  


實例代碼演示:spring-mvc

****************最後我會把本章的項目打包供下載************註釋部分我儘量詳細講解****************mvc

jar包導入.....(略)oracle

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>springMVC</display-name>
  
  <!-- 同時加載多個spring配置文件可用  -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
            classpath:spring-config/*.xml
        </param-value>
  </context-param>
  
  <!-- spring全局監聽 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <!-- 下面爲Druid默認配置,過濾掉多餘的url地址 -->
  <filter>
    <filter-name>DruidWebStatFilter</filter-name>
    <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
    <init-param>
      <param-name>exclusions</param-name>
      <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
    </init-param>
    <init-param>
      <param-name>principalSessionName</param-name>
      <param-value>_dest_login_</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>DruidWebStatFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- StatViewServlet是一個標準的Servlet -->
  <servlet>
    <servlet-name>DruidStatView</servlet-name>
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>DruidStatView</servlet-name>
    <url-pattern>/druid/*</url-pattern>
  </servlet-mapping>
  
  <!-- Spring Servlet,因爲把bean所有交給了SpringJap,因此Spring-mvc裏面如今爲空 -->
  <servlet>
    <servlet-name>springServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
  <!-- 首頁 -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

spring-mvc.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <!-- bean配置在spring-jpa.xml裏,因此這裏暫爲空,用來初始化spring容器-->
</beans>

spring-jpa.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:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
       default-lazy-init="true">

    <description>SpringJpa配置</description>
    
    <!-- 若是spring用了jpa,而且類型爲LocalContainerEntityManagerFactoryBean,則組件註冊在此配置文件出現便可,其他配置文件可忽略
           使用component來替代annotation 自動註冊bean, 並保證@Required、@Autowired的屬性被注入\ -->
    <context:component-scan base-package="com.spring.jpa"/>
    
    <!-- spring啓動時掃描項目路徑下的properties文件,後續用${key }方式取出對應值,這樣能夠代碼解耦和,後續只需修改properties文件便可 -->
    <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <!-- dataSourse鏈接池相關屬性,代碼不在此貼出,會放在打包好的項目裏面 -->
                <value>classpath:db.properties</value>
            </list>
        </property>
    </bean>
    
    <!-- 定義實體管理器工廠
         Jpa配置   LocalContainerEntityManagerFactoryBean這個選項Spring扮演了容器的角色。徹底掌管JPA -->
          點我查看 spring生成EntityManagerFactory的三種方式 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
           <!-- 指定數據源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 指定Jpa持久化實現廠商類,這裏以Hibernate爲例 -->
        <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
        <!-- 指定Entity實體類包路徑 -->
        <property name="packagesToScan" >
            <array>
                <value>com.spring.jpa</value>
            </array>
        </property>
        <!-- 指定JPA屬性;如Hibernate中指定是否顯示SQL的是否顯示、方言等 -->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
            </props>
        </property>
    </bean>
    
    <!-- 重要配置:啓用掃描並自動建立代理的功能  -->
    <jpa:repositories base-package="com.spring.jpa"  transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>
    
    <!-- Hibernate對Jpa的實現 -->
    <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

    <!-- Jpa 事務管理器  -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!-- 開啓註解事務 -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

    <!-- 數據源配置,使用應用內的DBCP數據庫鏈接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!--property name="driverClassName" value="${db.driverClass}"/-->
        <property name="url" value="${db.jdbcUrl}" />
        <property name="username" value="${db.user}" />
        <property name="password" value="${db.password}" />

        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${db.initialSize}" />
        <property name="minIdle" value="${db.minIdle}" />
        <property name="maxActive" value="${db.maxActive}" />
        <!-- 配置獲取鏈接等待超時的時間 --> 
        <property name="maxWait" value="${db.maxWait}" />
        <!-- 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${db.timeBetweenEvictionRunsMillis}" />
        <!-- 配置一個鏈接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}" />

        <property name="validationQuery" value="SELECT 'x' from dual" />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <!-- 打開PSCache,而且指定每一個鏈接上PSCache的大小 -->
        <property name="poolPreparedStatements" value="${db.poolPreparedStatements}" /> 
        <property name="maxPoolPreparedStatementPerConnectionSize" value="${db.maxPoolPreparedStatementPerConnectionSize}" />
    </bean>
    
    <!-- 啓動對@AspectJ(面向切面)註解的支持 --> 
    <aop:aspectj-autoproxy />
    
</beans>

 


  配置好了配置文件後,咱們該來寫對應的實體類,Dao,和service了,下面給出簡單的3個類:

User 實體類

package com.spring.jpa.user;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
 * User實體類
 * @author liuyt
 * @date  2014-10-30 下午2:27:37
 */
@Entity
@Table(name="T_SPRINGJPA_USER")
public class User {
    /**
     * 主鍵序列:DEFAULT_SUQUENCE 是我在oracle數據庫中建立的一個序列
     *           MY_SUQUENCE 是給自定義的序列建立一個引用名稱
     * 指個人主鍵生成策略 MY_SUQUENCE 使用的是 DEFAULT_SUQUENCE 這個序列。
     */
    @SequenceGenerator(name = "MY_SUQUENCE", sequenceName = "DEFAULT_SUQUENCE")
    @Id
    @GeneratedValue(generator="MY_SUQUENCE")
    private Long id;
    
    @Column(name="USER_NAME")
    private String userName;
    
    @Column(name="USER_PASSWORD")
    private String passWord;

    /*************GET****************SET***************/
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", userName=" + userName + ", passWord="
                + passWord + "]";
    }
}
User Entity

IUserDao 持久層(jpa對持久層簡化的核心基礎)

package com.spring.jpa.user;

import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

/**
 * 持久層接口
 * @author liuyt
 * @date  2014-10-30 下午2:09:48
 */
@Repository
public interface IUserDao extends PagingAndSortingRepository<User, Long>{
    /**
     * 經過前面的配置能夠看出,Spring 對 JPA 的支持已經很是強大,開發者無需過多關注 EntityManager 的建立、事務處理等 JPA 相關的處理
     * ***********************************************************************
     * 然而spring對Jpa的支持不止於此,它要從根本上來簡化咱們的業務代碼                        **
     * 在沒用使用jpa支持的時候,咱們的代碼應該是這樣的:                                    **
     *     一、IUserDao   持久層接口                                                **
     *     二、IUserDaoImpl   持久層實現類                                            **                
     *     三、IUserService    業務層接口.....後面不在列舉                                    **
     * 每寫一個實體類,都要衍生出五、6個類來對他進行操做,即便有了註解,咱們能夠依賴注入方式來拿到實現類,    **
     * 可是通用的CRUD等操做卻難免在每一個實現類裏聲明,你又說,我能夠定義一個父類,利用泛型反射原理就能夠了,    **
     * 但那樣你還須要爲每一個Dao聲明本身的實現類來繼承你的父類                                    **
     * ***********************************************************************
     * 那麼問題來了...(不是挖掘機技術)對持久層的簡化技術哪家強?      Spring Data Jpa            **
     * 你惟一要作的就只是聲明持久層的接口,來繼承他自身已經封裝好的持久層接口,正如本類IUserDao同樣        **
     * 可以使用的接口有:                                                            **********
     *     Repository:是 Spring Data的一個核心接口,它不提供任何方法,開發者須要在本身定義的接口中聲明須要的方法。**
     *     CrudRepository:繼承Repository,提供增刪改查方法,能夠直接調用。                            **
     *     PagingAndSortingRepository:繼承CrudRepository,具備分頁查詢和排序功能(本類實例)        **
     *     JpaRepository:                         繼承PagingAndSortingRepository,針對JPA技術提供的接口            **
     *     JpaSpecificationExecutor:          能夠執行原生SQL查詢                                    **
     *    繼承不一樣的接口,有兩個不一樣的泛型參數,他們是該持久層操做的類對象和主鍵類型。                            **
     *********************************************************************************
     */
}

  這裏爲了方便演示,就不寫業務層接口了,直接上業務層service代碼

UserService 業務層

package com.spring.jpa.user;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
/**
 * User業務層,依賴持久層  IUserDao
 * @author liuyt
 * @date  2014-10-30 下午2:37:21
 */
@Service
public class UserService {
    // 推薦用Resource來替代AutoWrite註解
    @Resource
    private IUserDao userDao;
    
    // 新增用戶
    public void saveUser(User user) {
        userDao.save(user);
    }
    
    // 刪除用戶,參數也能夠爲一個含有id的User對象
    public void deleteUser(Long id) {
        userDao.delete(id);
    }
    
    // 查詢全部user對象,findOne爲查詢單個
    public List<User> findAllUsers() {
        return (List<User>) userDao.findAll();
    }
    
    /**
     * 根據一個分頁對象查詢user集合(還能夠添加一個Store排序屬性)
     * PageRequest    是spring本身封裝的請求分頁類,實現了Pageable接口,包涵從請求中得到的分頁屬性(當前頁和大小)和獲取方法
     * 經過調用分頁方法,返回一個Page<>一個泛型集合的分頁對象,裏面包涵了經過查詢計算出的各個屬性和結果集
     * 詳細類結構和屬性請參閱源碼
     * @param page
     * @return
     */
    public Page<User> findAllUserByPage(PageRequest page) {
        return (Page<User>) userDao.findAll(page);
    }
}

 


  至此,總體SpringJpa框架就搭建好了,剩下的就是寫頁面和控制器進行測試了,這裏不作演示,由於會在下一章節利用SpringUnit單元測試,經過註解的方式進行方法測試,詳情請移步:待更新...


   項目war包下載:點我下載

總結:

  •  在學習期間可能jar包的導入會很頭疼,由於各種框架的jar有時候會出現不兼容的狀況(點擊下載本章節jar包)到期請提醒
  •    本章節用到的Druid鏈接池配置,詳細配置請異步度娘
  •    spring-jpa.xml裏面能夠針對不一樣需求,能夠選擇不一樣的EntityManagerFactory實體類管理
  •    別忘記<jpa:repositories />標籤的配置,他用來聲明Jpa涉及到的包路徑
  •    SpringJpa集成了聲明式事務,記得開啓註解事務便可
  •    持久層的實現接口有不少,根據需求靈活選擇(本章演示有關分頁的接口,由於網上對該接口的介紹都比較粗略)
  •    未涉及:其餘功能:如Query查詢,Dao接口方法的新增                    
相關文章
相關標籤/搜索