Spring Data JPA 入門篇

Spring Data JPA是什麼

它是Spring基於ORM框架(如hibernate,Mybatis等)、JPA規範(Java Persistence API)封裝的一套 JPA應用框架,可以使開發者用極簡的代碼便可實現對數據的訪問和操做。他提供了包括增刪改查在內的經常使用功能,且易於擴展!學習並使用Spring Data JPA能夠極大提升開發效率。java

Spring Data JPA有什麼mysql

主要看看SpringDataJPA提供的編程接口spring

  • Repository:最頂層的接口,是一個空接口,目的是爲了統一全部的Repository的類型,且能讓組件掃描的時候自動識別。
  • CrudRepository:Repository的子接口,提供CRUD的功能
  • PagingAndSortingRepository:CrudRepository的子接口,添加分頁排序的功能
  • JpaRepository:PagingAndSortingRepository的子接口,增長批量操做等功能
  • JPASpecificationExecutor:用來作複雜查詢的接口

 

創建項目:用戶管理

配置文件persistent.xmlsql

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="userPU" transaction-type="RESOURCE_LOCAL">
        <!--jpa的提供者-->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <!--聲明數據庫鏈接的驅動-->
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <!--jdbc數據庫的鏈接地址-->
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value="123456"/>
            <!--配置方言-->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
            <!--激活查詢日誌功能-->
            <property name="hibernate.show_sql" value="true"/>
            <!--優雅地輸出Sql-->
            <property name="hibernate.format_sql" value="true"/>
            <!--添加一條解釋型標註-->
            <property name="hibernate.use_sql_comments" value="false"/>
            <!--配置如何根據java模型生成數據庫表結構,經常使用update,validate-->
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

applicationContext.xml數據庫

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

    <!--第一步-->
    <!--定義服務層代碼存放的包掃描路徑-->
    <context:component-scan base-package="com.jike.usermanage.service" />

    <!--第二步-->
    <!--定義實體的工廠bean-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="userPU" />
        <property name="persistenceXmlLocation" value="classpath:persistence.xml"></property>
    </bean>

    <!--第三步-->
    <!--定義事務管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--第四步-->
    <!--定義repository接口的存放目錄-->
    <!--定義接口實現的後綴,一般用Impl--,若是咱們不想使用JPA提供的方法,咱們能夠本身實現,文件後綴爲Impl>
    <!--定義實體工廠的引用-->
    <!--定義事務管理器的引用-->
       <jpa:repositories base-package="com.jike.usermanage.repository"
                         repository-impl-postfix="Impl" 
                         entity-manager-factory-ref="entityManagerFactory" 
                         transaction-manager-ref="transactionManager"/>
    <!--第五步-->
    <!--聲明採用註解的方式申明事務-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

實體類User.java編程

 

package com.jike.usermanage.model;

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


@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    private String address;
    private String phone;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}

Dao層UserRepository.java:這個類須要繼承JpaRepository<User,Integer>,Integer表示User表中的主鍵類型app

package com.jike.usermanage.repository;

import java.util.List;

import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import com.jike.usermanage.model.User;

public interface UserRepository extends JpaRepository<User, Integer> {

    // 查詢需求: 從數據庫中查詢電話號碼(phone)以指定字符串開始(例如:136)的,而且地址(address)中包含指定字符串(例如:路)的記錄
    // select * from user where phone like '136%' and address like '%路%' order
    // by phone desc limit 0,2
    List<User> findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc(
            String phone, String address);

    List<User> findTop2ByPhoneStartingWithAndAddressContaining(String phone,
            String address, Sort sort);

    Page<User> findByPhoneStartingWithAndAddressContaining(String phone,
            String address, Pageable pageable);
}

Service層:框架

 

package com.jike.usermanage.service;

import java.util.List;

import org.springframework.data.domain.Page;

import com.jike.usermanage.exception.UserNotFound;
import com.jike.usermanage.model.User;

public interface UserService {
    // 添加用戶
    public void addUser(User user);

    // 修改用戶
    public User updateUser(User user) throws UserNotFound;

    // 刪除用戶,根據用戶編號刪除
    public User deleteUser(int id) throws UserNotFound;

    // 查詢單個用戶
    public User getUser(int id);

    // 查詢全部用戶
    public List<User> getUsers();

    // 不分頁帶條件查詢
    public List<User> getUsersByConditionNoPage(String phone, String address);

    // 帶分頁條件查詢(須要獲得用戶列表而且獲得分頁信息)
    public Page<User> getUsersByConditionWithPage(String phone, String address,
            Integer page, Integer pageSize);
    // 帶分頁條件查詢(獲得用戶列表)
    // public List<User> getUsersByCondition(String phone,String address,Integer
    // page,Integer pageSize);
}

ServiceImpldom

package com.jike.usermanage.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import com.jike.usermanage.exception.UserNotFound;
import com.jike.usermanage.model.User;
import com.jike.usermanage.repository.UserRepository;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void addUser(User user) {
        userRepository.save(user);

    }

    @Override
    public User updateUser(User user) throws UserNotFound {
        User userUpdate = userRepository.findOne(user.getId());
        if (userUpdate == null)
            throw new UserNotFound();
        if (user.getName() != null)
            userUpdate.setName(user.getName());
        if (user.getAddress() != null)
            userUpdate.setAddress(user.getAddress());
        if (user.getPhone() != null)
            userUpdate.setPhone(user.getPhone());
        userRepository.save(userUpdate);
        return userUpdate;
    }

    @Override
    public User deleteUser(int id) throws UserNotFound {
        User userDelete = userRepository.findOne(id);
        if (userDelete == null)
            throw new UserNotFound();
        userRepository.delete(userDelete);
        return userDelete;
    }

    @Override
    public User getUser(int id) {

        return userRepository.findOne(id);
    }

    @Override
    public List<User> getUsers() {

        return userRepository.findAll();
    }

    @Override
    public Page<User> getUsersByConditionWithPage(String phone, String address,
            Integer page, Integer pageSize) {

        // 不排序
        Page<User> userPage = userRepository
                .findByPhoneStartingWithAndAddressContaining(phone, address,
                        new PageRequest(page, pageSize));

        // 排序

        // 第一種排序方式
        // Page<User> userPage =
        // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new
        // PageRequest(page, pageSize,new Sort(Direction.ASC,"name","phone")));

        // 第二種排序方式
        // Order order = new Order(Direction.ASC,"phone");
        // Page<User> userPage =
        // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new
        // PageRequest(page, pageSize,new Sort(order));

        // 第三種排序方式
        // List<Order> orders = new ArrayList<Order>();
        // orders.add(new Order(Direction.DESC,"name"));
        // orders.add(new Order(Direction.ASC,"phone"));
        // Page<User> userPage =
        // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new
        // PageRequest(page, pageSize,new Sort(orders));

        return userPage;

    }

    @Override
    public List<User> getUsersByConditionNoPage(String phone, String address) {

        return userRepository
                .findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc(
                        phone, address);

        // return
        // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone,
        // address, new Sort(Direction.ASC,"phone"));

        // Order order = new Order(Direction.ASC,"phone");
        // return
        // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone,
        // address, new Sort(order));

        // List<Order> orders = new ArrayList<Order>();
        // orders.add(new Order(Direction.DESC,"name"));
        // orders.add(new Order(Direction.ASC,"phone"));
        // return
        // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone,
        // address, new Sort(orders);

    }

}

異常類ide

package com.jike.usermanage.exception;

public class UserNotFound extends Exception {

}

JpaRepository接口方法:

  delete刪除或批量刪除

  findAll查找全部

  findOne查找單個

  save保存單個或批量保存

  saveAndFlush保存並刷新到數據庫

查詢操做的基本實現----基於方法名解析

JpaRepository支持接口規範方法名查詢。意思是若是在接口中定義的查詢方法符合他的命名規則,就能夠不用寫實現。

  例如:findByName這個方法表示從數據庫中查詢Name這個屬性等於XXX的全部記錄,相似於SQL語句:select * from xxTable where name=xxx這種形式

  1. 方法名須要在接口中設定

  2.必須符合必定的命名規範

    find+全局修飾+By+實體的屬性名稱+限定詞+鏈接詞+...(其餘屬性實體)+OrderBy+排序屬性+排序方向

  例如:findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String firstName,String lastName){....}

  其中:Distinct是全局修飾(非必須),FirstName和LastName是實體的屬性名,And是鏈接詞,IgnoreCase是限定詞,Age是排序屬性,Dest是排序方向,限定詞和鏈接詞統稱爲"關鍵詞"

  經常使用詞以下:

    全局修飾:Distinct,Top,First

    關鍵詞:IsNull,InNotNull,Like,NotLike,Containing,In,NotIn,IgnoreCase,Betwwen,Equals,LessThan,GreaterThan,After,Before

    排序方向:Asc,Desc

    鏈接詞:And,Or

    

項目代碼下載

相關文章
相關標籤/搜索