黑馬程序員spring data jpa 2019年第一版本


第一步首先創建一個maven工程,導入對於的pom依賴

 

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.cib.com</groupId>
  <artifactId>heimaspringdatajpa</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
        <!--版本鎖定-->
        <spring.version>5.0.2.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>

    <dependencies>
        <!-- junit單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</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-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- spring對orm框架的支持包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <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>

        <!-- spring end -->

        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->

     
     

        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!-- spring data jpa 的坐標-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- el beg 使用spring data jpa 必須引入 -->
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>2.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.4</version>
        </dependency>
        <!-- el end -->
    </dependencies>
</project>

 

1、接下來創建jpa的核心配置文件

jpa的核心配置文件必須放在類路徑的meta-info文件夾下面,命名也必須滿足對於的規則

PA規范要求在類路徑的META-INF目錄下放置persistence.xml, 文件的名稱是固定的,配置模板如下:

<!--必須要有name屬性,不能為空 -->
<persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">

這里

 

 如果是分布式事務管理,這里就要配置為JTA,這里只操作一個數據庫,這里不存在分布式事務,這里設置為RESOURCE_LOCAl

 

 

 

 

 persistence.xml的內容如下所示

<?xml version="1.0" encoding="UTF-8"?>
 <persistence version="2.0" xmlns="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_2_0.xsd">
    
    <!--必須要有name屬性,不能為空 -->
     <persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">
          <!--可選 -->
          <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
          
          <!--廠商的特定屬性 -->
        
          
          <properties>
          <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?useUnicode=true&amp;characterEncoding=UTF-8" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="123456" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
        </properties>
     </persistence-unit>
             
 </persistence>

 

接下來,我們要編寫實體類,創建對於的數據庫表

創建客戶的數據庫表

drop table if exists cst_customer;
/*創建客戶表*/
CREATE TABLE cst_customer (
  cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
  cust_name varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
  cust_source varchar(32) DEFAULT NULL COMMENT '客戶信息來源',
  cust_industry varchar(32) DEFAULT NULL COMMENT '客戶所屬行業',
  cust_level varchar(32) DEFAULT NULL COMMENT '客戶級別',
  cust_address varchar(128) DEFAULT NULL COMMENT '客戶聯系地址',
  cust_phone varchar(64) DEFAULT NULL COMMENT '客戶聯系電話',
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8MB4;

————————————————
版權聲明:本文為CSDN博主「底層_碼農」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_40794973/article/details/98895832

注:表可以不用創建

3)創建、編寫實體類和數據庫表的映射配置[重點]

注解描述

@Entity:聲明實體類】
@Table : 配置實體類和表的映射關系 , name : 配置數據庫表的名稱
/**
     * @Id:聲明主鍵的配置
     * @GeneratedValue:配置主鍵的生成策略
     *      strategy
     *          GenerationType.IDENTITY :自增,mysql
     *                 * 底層數據庫必須支持自動增長(底層數據庫支持的自動增長方式,對id自增)
     *          GenerationType.SEQUENCE : 序列,oracle
     *                  * 底層數據庫必須支持序列
     *          GenerationType.TABLE : jpa提供的一種機制,通過一張數據庫表的形式幫助我們完成主鍵自增
     *          GenerationType.AUTO : 由程序自動的幫助我們選擇主鍵生成策略
     * @Column:配置屬性和字段的映射關系
     *      name:數據庫表中字段的名稱
     */
    /**
     * 客戶編號(主鍵)
     */

 

 

GenerationType.IDENTITY :自增,mysql
* * 底層數據庫必須支持自動增長(底層數據庫支持的自動增長方式,對id自增) 必須和mysql中的  AUTO_INCREMENT一一對象,cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',

@Column:配置屬性和字段的映射關系
* name:數據庫表中字段的名稱

package com.itcast.domain;

import java.io.Serializable;

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

/**
 * 客戶的實體類
 *      配置映射關系
 *
 *   1.實體類和表的映射關系
 *      @Entity:聲明實體類
 *      @Table : 配置實體類和表的映射關系
 *          name : 配置數據庫表的名稱
 *   2.實體類中屬性和表中字段的映射關系
 */
@Entity
@Table(name = "cst_customer")
public class Customer implements Serializable {
 
    /**
     * @Id:聲明主鍵的配置
     * @GeneratedValue:配置主鍵的生成策略
     *      strategy
     *          GenerationType.IDENTITY :自增,mysql
     *                 * 底層數據庫必須支持自動增長(底層數據庫支持的自動增長方式,對id自增)
     *          GenerationType.SEQUENCE : 序列,oracle
     *                  * 底層數據庫必須支持序列
     *          GenerationType.TABLE : jpa提供的一種機制,通過一張數據庫表的形式幫助我們完成主鍵自增
     *          GenerationType.AUTO : 由程序自動的幫助我們選擇主鍵生成策略
     * @Column:配置屬性和字段的映射關系
     *      name:數據庫表中字段的名稱
     */
    /**
     * 客戶編號(主鍵)
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;
    /**
     * 客戶名稱(公司名稱)
     */
    @Column(name = "cust_name")
    private String custName;
    /**
     * 客戶信息來源
     */
    @Column(name="cust_source")
    private String custSource;
    /**
     * 客戶所屬行業
     */
    @Column(name="cust_industry")
    private String custIndustry;
    /**
     * 客戶級別
     */
    @Column(name="cust_level")
    private String custLevel;
    /**
     * 客戶聯系地址
     */
    @Column(name="cust_address")
    private String custAddress;
    /**
     * 客戶聯系電話
     */
    @Column(name="cust_phone")
    private String custPhone;
    public Long getCustId() {
        return custId;
    }
    public void setCustId(Long custId) {
        this.custId = custId;
    }
    public String getCustName() {
        return custName;
    }
    public void setCustName(String custName) {
        this.custName = custName;
    }
    public String getCustSource() {
        return custSource;
    }
    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }
    public String getCustIndustry() {
        return custIndustry;
    }
    public void setCustIndustry(String custIndustry) {
        this.custIndustry = custIndustry;
    }
    public String getCustLevel() {
        return custLevel;
    }
    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }
    public String getCustAddress() {
        return custAddress;
    }
    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }
    public String getCustPhone() {
        return custPhone;
    }
    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }
    
    
}

 

接下來我們就可以編寫一個測試類,測試對於的jpa的操作


/**
* 測試jpa的保存
* 案例:保存一個客戶到數據庫中
* Jpa的操作步驟
* 1.加載配置文件創建工廠(實體管理器工廠)對象
* 2.通過實體管理器工廠獲取實體管理器
* 3.獲取事務對象,開啟事務
* 4.完成增刪改查操作
* 5.提交事務(回滾事務)
* 6.釋放資源
*/

package com.itcast.cn;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.junit.Test;

import com.itcast.domain.Customer;

public class TestJpa {

    
    /**
     * 測試jpa的保存
     *      案例:保存一個客戶到數據庫中
     *  Jpa的操作步驟
     *     1.加載配置文件創建工廠(實體管理器工廠)對象
     *     2.通過實體管理器工廠獲取實體管理器
     *     3.獲取事務對象,開啟事務
     *     4.完成增刪改查操作
     *     5.提交事務(回滾事務)
     *     6.釋放資源
     */
    @Test
    public void testSave() {
        //1.加載配置文件創建工廠(實體管理器工廠)對象
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
        //2.通過實體管理器工廠獲取實體管理器
        EntityManager em = factory.createEntityManager();
     
        //3.獲取事務對象,開啟事務
        EntityTransaction tx = em.getTransaction(); //獲取事務對象
        tx.begin();//開啟事務
        try{
            //4.完成增刪改查操作:保存一個客戶到數據庫中
            Customer customer = new Customer();
            customer.setCustName("蔡徐坤");
            customer.setCustIndustry("明星");
            customer.setCustSource("bibi");
            //保存
            em.persist(customer); //保存操作
            //5.提交事務
            tx.commit();
        }catch (Exception e){
            tx.rollback();//回滾事務
            e.printStackTrace();
        }finally {
            //6.釋放資源
            em.close();
            //關閉工廠
            factory.close();
        }
     
    }
}

 

運行的sql語句如下所示

log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)

GenerationType.TABLE : jpa提供的一種機制,通過一張數據庫表的形式幫助我們完成主鍵自增,jpa會另外生成一張表幫助我們進行主鍵的管理

 

 GenerationType.AUTO : 由程序自動的幫助我們選擇主鍵生成策略

 

 

 多個線程在內存中共享一份Factory對象,減少Factory對象創建消耗資源

 

 采用靜態代碼塊的方法,減少Factory資源創建消耗性能的問題

1. 抽取JPAUtil工具類

package com.itcast.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * 解決實體管理器工廠的浪費資源和耗時問題
 * 通過靜態代碼塊的形式,當程序第一次訪問此工具類時,創建一個公共的實體管理器工廠對象
 *
 * 第一次訪問getEntityManager方法:經過靜態代碼塊創建一個factory對象,再調用方法創建一個EntityManager對象
 * 第二次方法getEntityManager方法:直接通過一個已經創建好的factory對象,創建EntityManager對象
 */
public class JpaUtils {
    private static EntityManagerFactory factory;
 
    static {
        //1.加載配置文件,創建entityManagerFactory
        factory = Persistence.createEntityManagerFactory("myJpa");
    }
    /**
     * 獲取EntityManager對象
     */
    public static EntityManager getEntityManager() {
        return factory.createEntityManager();
    }
}

 

我們在編寫一個測試類進行測試

解決創建 EntityManagerFactory  浪費資源問題 

3. 測試查詢
查詢有兩個方法,注意區別

package com.itcast.cn;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.junit.Test;

import com.itcast.domain.Customer;
import com.itcast.utils.JpaUtils;

public class TestJpa {

    
    /**
     * 測試jpa的保存
     *      案例:保存一個客戶到數據庫中
     *  Jpa的操作步驟
     *     1.加載配置文件創建工廠(實體管理器工廠)對象
     *     2.通過實體管理器工廠獲取實體管理器
     *     3.獲取事務對象,開啟事務
     *     4.完成增刪改查操作
     *     5.提交事務(回滾事務)
     *     6.釋放資源
     */
    @Test
    public void testSave() {
        //1.加載配置文件創建工廠(實體管理器工廠)對象
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
        //2.通過實體管理器工廠獲取實體管理器
        EntityManager em = factory.createEntityManager();
     
        //3.獲取事務對象,開啟事務
        EntityTransaction tx = em.getTransaction(); //獲取事務對象
        tx.begin();//開啟事務
        try{
            //4.完成增刪改查操作:保存一個客戶到數據庫中
            Customer customer = new Customer();
            customer.setCustName("蔡徐坤");
            customer.setCustIndustry("明星");
            customer.setCustSource("bibi");
            //保存
            em.persist(customer); //保存操作
            //5.提交事務
            tx.commit();
        }catch (Exception e){
            tx.rollback();//回滾事務
            e.printStackTrace();
        }finally {
            //6.釋放資源
            em.close();
            //關閉工廠
            factory.close();
        }
     
    }
    
    @Test
    public void testtestSave02(){
        //1.獲取工廠(實體管理器工廠)對象
        EntityManager em = JpaUtils.getEntityManager();
        //3.獲取事務對象,開啟事務
        EntityTransaction tx = em.getTransaction(); //獲取事務對象
        tx.begin();//開啟事務
        //4.完成增刪改查操作:保存一個客戶到數據庫中
        Customer customer = new Customer();
        customer.setCustName("蔡徐坤");
        customer.setCustIndustry("明星");
        customer.setCustSource("bibi");
        //保存
        em.persist(customer); //保存操作
        //5.提交事務
        tx.commit();
        //6.釋放資源
        em.close();
    }
    
    /**
     * 根據id查詢客戶
     *  使用find方法查詢:
     *      1.查詢的對象就是當前客戶對象本身
     *      2.在調用find方法的時候,就會發送sql語句查詢數據庫
     *
     *  立即加載
     */
    @Test
    public  void testFind() {
        //1.通過工具類獲取entityManager
        EntityManager entityManager = JpaUtils.getEntityManager();
        //3.增刪改查 -- 根據id查詢客戶
        /**
         * find : 根據id查詢數據
         *      class:查詢數據的結果需要包裝的實體類類型的字節碼
         *      id:查詢的主鍵的取值
         * 沒有返回 null
         */
        Customer customer = entityManager.find(Customer.class, 1L);//打斷點
        //不管打不打印(使用),執行到上一條語句時,都會發送SQL語句
        //System.out.print(customer);
        //class com.bug.domain.Customer
        System.out.println(customer.toString());
        //5.釋放資源
        entityManager.close();

    }
    
    /**
     * 根據id查詢客戶
     *      getReference方法
     *          1.獲取的對象是一個動態代理對象
     *          2.調用getReference方法不會立即發送sql語句查詢數據庫
     *              * 當調用查詢結果對象的時候,才會發送查詢的sql語句:什么時候用,什么時候發送sql語句查詢數據庫
     *
     * 延遲加載(懶加載)
     *      * 得到的是一個動態代理對象
     *      * 什么時候用,什么使用才會查詢
     */
    @Test
    public  void testReference() {
        //1.通過工具類獲取entityManager
        EntityManager entityManager = JpaUtils.getEntityManager();
        //3.增刪改查 -- 根據id查詢客戶
        /**
         * getReference : 根據id查詢數據
         *      class:查詢數據的結果需要包裝的實體類類型的字節碼
         *      id:查詢的主鍵的取值
         */
        Customer customer = entityManager.getReference(Customer.class, 1L);//打斷點
        //這里不打印(不使用)就不會發送SQL語句
        //System.out.print(customer);
        //class com.bug.domain.Customer_$$_jvst88e_0 代理對象
        System.out.println("\n\n");
        System.out.println(customer.toString());
        //5.釋放資源
        entityManager.close();
    }


}

 

//3.增刪改查 -- 根據id查詢客戶
/**
* getReference : 根據id查詢數據
* class:查詢數據的結果需要包裝的實體類類型的字節碼
* id:查詢的主鍵的取值
*/

getReference 是懶加載,在find查詢語句的時候不會發起sql語句查詢,在實際使用使用System.out.print(customer)的時候才發起sql語句進行查詢,返回的查詢結果是一個代理對象

4. 測試刪除

@Test
    public  void testRemove() {
        //1.通過工具類獲取entityManager
        EntityManager entityManager = JpaUtils.getEntityManager();
        //3.增刪改查 -- 刪除客戶
        //3.獲取事務對象,開啟事務
        EntityTransaction tx = entityManager.getTransaction(); //獲取事務對象
        tx.begin();//開啟事務
        //i 根據id查詢客戶
        Customer customer = entityManager.find(Customer.class, 1L);
        System.out.println(customer);
        if(customer != null){
            //ii 調用remove方法完成刪除操作
            entityManager.remove(customer);
        }
        //5.提交事務
        tx.commit();
        //5.釋放資源
        entityManager.close();
    }

 

7.JPA中的復雜查詢
JPQL全稱Java Persistence Query Language,Java持久化查詢語言(JPQL),它是一種可移植的查詢語言,旨在以面向對象表達式語言的表達式,將SQL語法和簡單查詢語義綁定在一起·使用這種語言編寫的查詢是可移植的,可以被編譯成所有主流數據庫服務器上的SQL。

其特征與原生SQL語句類似,並且完全面向對象,通過類名和屬性訪問,而不是表名和表的屬性。

 

 jpql語句不能寫select *,但是能夠寫select 加上對象的屬性值

查詢數據庫 表中存在多少條記錄

 

 

//統計查詢
    @Test
    public void findCount() {
        EntityManager em = null;
        EntityTransaction tx = null;
        try {
            //獲取實體管理對象
            em = JPAUtil.getEntityManager();
            //獲取事務對象
            tx = em.getTransaction();
            tx.begin();
            // 查詢全部客戶
            // 1.創建query對象
            String jpql = "select count(custId) from Customer";
            Query query = em.createQuery(jpql);
            // 2.查詢並得到返回結果
            Object count = query.getSingleResult(); // 得到集合返回類型
            System.out.println(count);
            tx.commit();
        } catch (Exception e) {
            // 回滾事務
            tx.rollback();
            e.printStackTrace();
        } finally {
            // 釋放資源
            em.close();
        }
    }
 
————————————————
版權聲明:本文為CSDN博主「I Java」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zlx_508/article/details/97005499

 

記錄總數只有一條記錄,使用getSingleResult,返回一條記錄

分頁查詢

 

 0表示查詢第一頁,2表示第一頁顯示2條記錄

//分頁查詢客戶
    @Test
    public void findPaged () {
        EntityManager em = null;
        EntityTransaction tx = null;
        try {
            //獲取實體管理對象
            em = JPAUtil.getEntityManager();
            //獲取事務對象
            tx = em.getTransaction();
            tx.begin();
 
            //創建query對象
            String jpql = "from Customer";
            Query query = em.createQuery(jpql);
            //起始索引
            query.setFirstResult(0);
            //每頁顯示條數
            query.setMaxResults(2);
            //查詢並得到返回結果
            List list = query.getResultList(); //得到集合返回類型
            for (Object object : list) {
                System.out.println(object);
            }
            tx.commit();
        } catch (Exception e) {
            // 回滾事務
            tx.rollback();
            e.printStackTrace();
        } finally {
            // 釋放資源
            em.close();
        }
    }
————————————————
版權聲明:本文為CSDN博主「I Java」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zlx_508/article/details/97005499

 

接下來我們講解條件查詢

 

 

//條件查詢
    @Test
    public void findCondition () {
        EntityManager em = null;
        EntityTransaction tx = null;
        try {
            //獲取實體管理對象
            em = JPAUtil.getEntityManager();
            //獲取事務對象
            tx = em.getTransaction();
            tx.begin();
            //創建query對象
            String jpql = "from Customer where custName like ? ";
            Query query = em.createQuery(jpql);
            //對占位符賦值,從1開始
            query.setParameter(1, "傳智播客%");
            //查詢並得到返回結果
            Object object = query.getSingleResult(); //得到唯一的結果集對象
            System.out.println(object);
            tx.commit();
        } catch (Exception e) {
            // 回滾事務
            tx.rollback();
            e.printStackTrace();
        } finally {
            // 釋放資源
            em.close();
        }
    }
————————————————
版權聲明:本文為CSDN博主「I Java」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zlx_508/article/details/97005499

 接下來重點講解spring -data-jpa

這里配置文件有點問題,不清楚的看佟剛spring data的視頻教程

 

 

 

 

 

 pom.xml的依賴如下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.cib.com</groupId>
  <artifactId>heimaspringdatajpa</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
        <!--版本鎖定-->
        <spring.version>5.0.2.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>

    <dependencies>
        <!-- junit單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</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-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- spring對orm框架的支持包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <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>

        <!-- spring end -->

        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->

     
     

        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!-- spring data jpa 的坐標-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- el beg 使用spring data jpa 必須引入 -->
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>2.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.4</version>
        </dependency>
        <!-- el end -->
    </dependencies>
</project>

 

db.properties的配置如下

jdbc.user=root
jdbc.password=123456
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///jpa

 

<?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: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.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 配置自動掃描的包 -->
    <context:component-scan base-package="com.atguigu.springdata"></context:component-scan>

    <!-- 1. 配置數據源 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <bean id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>    
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        
        <!-- 配置其他屬性 -->
    </bean>

    <!-- 2. 配置 JPA 的 EntityManagerFactory -->
    <bean id="entityManagerFactory" 
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
        </property>
        <property name="packagesToScan" value="com.atguigu.springdata"></property>
        <property name="jpaProperties">
            <props>
                <!-- 二級緩存相關 -->
                <!--  
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
                -->
                <!-- 生成的數據表的列的映射策略 -->
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <!-- hibernate 基本屬性 -->
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

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

    <!-- 4. 配置支持注解的事務 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 5. 配置 SpringData -->
    <!-- 加入  jpa 的命名空間 -->
    <!-- base-package: 掃描 Repository Bean 所在的 package -->
    <jpa:repositories base-package="com.atguigu.springdata"
        entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

</beans>

 

這里有幾個配置很關鍵

<jpa:repositories base-package="com.atguigu.springdata" 指定掃描@Reporisty注解的包

<property name="packagesToScan" value="com.atguigu.springdata"></property>指定@Entiry注解的包

<context:component-scan base-package="com.atguigu.springdata"></context:component-scan>指定spring @service @compent所在的包路徑

接下來我們創建包com.atguigu.springdata,所有在的操作都在這個包下面

接下來我們創建實體類

package com.atguigu.springdata;
import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

@Entity // 聲明此類是個實體類 需要導入javax.persistence.Entity;

@Table(name = "cst_customer") //需要將該類對應到數據庫中的哪一個表中,name中填表的名稱

public class Customer {



@Id //聲明主鍵 

@GeneratedValue(strategy = GenerationType.IDENTITY) //聲明主鍵的生成策略為自動遞增

//mysql使用自增模式,orcle 使用序列模式

@Column(name = "cust_id") //設置該屬性和數據庫中的哪一個字段對應

private Long custId;

 

@Column(name = "cust_name")

private String custName;

 

@Column(name = "cust_source")

private String custSource;

 

@Column(name = "cust_level")

private String custLevel;

 

@Column(name = "cust_industry")

private String cusIndustry;

 

@Column(name = "cust_phone")

private String custPhone;

 

@Column(name = "cust_address")

private String custAddress;



public Long getCustId() {

return custId;

}



public void setCustId(Long custId) {

this.custId = custId;

}



public String getCustName() {

return custName;

}



public void setCustName(String custName) {

this.custName = custName;

}



public String getCustSource() {

return custSource;

}



public void setCustSource(String custSource) {

this.custSource = custSource;

}



public String getCustLevel() {

return custLevel;

}



public void setCustLevel(String custLevel) {

this.custLevel = custLevel;

}



public String getCusIndustry() {

return cusIndustry;

}



public void setCusIndustry(String cusIndustry) {

this.cusIndustry = cusIndustry;

}



public String getCustPhone() {

return custPhone;

}



public void setCustPhone(String custPhone) {

this.custPhone = custPhone;

}



public String getCustAddress() {

return custAddress;

}



public void setCustAddress(String custAddress) {

this.custAddress = custAddress;

}



@Override

public String toString() {

return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource

+ ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone

+ ", custAddress=" + custAddress + "]";

}

 

}

 

實體類創建成功之后,接下來我們就可以編寫jpa的接口進行增刪改查的操作了,只需要編寫jpa接口,不需要編寫jpa的實現類

關鍵點:

1.編寫dao層的接口就可以了,不需要dao接口的實現類

2、編寫的dao接口的規范如下

 

 SpringDataJPA通過實現接口(代理的形式)進行簡單的CRUD

https://blog.csdn.net/qq_42041712/article/details/94451572

JpaRepository<Customer,Long> 第一個參數是我們要操作的實體類類型,第二個參數是實體類的主鍵

JpaSpecificationExecutor<Customer> 參數是我們要操作的實體類的類型

package com.atguigu.springdata;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 
public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
 
}

 

接下來編寫好接口之后,就可以進行增加刪除操作數據庫了,注意CustomerDao沒有使用注解,只要放在<jpa:repositories base-package="com.atguigu.springdata"對於的包下面就可以了

 

 我們可以編寫一個測試類進行操作,首先保證數據庫中存在數據

 

 

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.atguigu.springdata.CustomerDao;
import com.itcast.domain.Customer;
import com.itcast.utils.JpaUtils;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest {

    @Autowired
    private CustomerDao dao;
    
    @Test
    public  void testFind() {
        
      com.atguigu.springdata.Customer customer = dao.findOne((long) 2);
      System.out.println(customer.toString());
    }
    
}

 

測試的結果如下

 

 

在eclipse中查看一個類及其父類中的所有方法和屬性
只需要連續按兩次Ctrl+O

JpaRepository默認實現了下面的方法

 

 

在eclipse中查看一個類的集成關系
只需要連續按兩次Ctrl+T

 

 JpaRepository繼承自PagingAndSortingRepository,PagingAndSortingRepository繼承自CrudRepository,CrudRepository集成自Repository

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest {

    @Autowired
    private CustomerDao customerDao;
    
    @Test
    public  void testFind() {
        
      com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
      System.out.println(customer.toString());
    }
    
    /**

     * 保存客戶:調用save(obj)方法

     */

    @Test

    public void testSave() {

        Customer c = new Customer();

        c.setCustName("傳智播客");

        customerDao.save(c);

    }

   

    /**

     * 修改客戶:調用save(obj)方法

     *      對於save方法的解釋:如果執行此方法是對象中存在id屬性,即為更新操作會先根據id查詢,再更新   

     *                      如果執行此方法中對象中不存在id屬性,即為保存操作

     *         

     */

    @Test

    public void testUpdate() {

        //根據id查詢id為1的客戶

        Customer customer = customerDao.findOne(1l);

        //修改客戶名稱

        customer.setCustName("傳智播客順義校區");

        //更新

        customerDao.save(customer);

    }
    
}

 

/**

* 根據id刪除:調用delete(id)方法

*/

@Test

public void testDelete() {

customerDao.delete(1l);

}

 

 

 

 

 

 

 

 

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest {

    @Autowired
    private CustomerDao customerDao;
    
    @Test
    public  void testFind() {
        
      com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
      System.out.println(customer.toString());
    }
    
    /**

     * 保存客戶:調用save(obj)方法

     */

    @Test

    public void testSave() {

        Customer c = new Customer();

        c.setCustName("傳智播客");

        customerDao.save(c);

    }

   

    /**

     * 修改客戶:調用save(obj)方法

     *      對於save方法的解釋:如果執行此方法是對象中存在id屬性,即為更新操作會先根據id查詢,再更新   

     *                      如果執行此方法中對象中不存在id屬性,即為保存操作

     *         

     */

    @Test

    public void testUpdate() {

        //根據id查詢id為1的客戶

        Customer customer = customerDao.findOne(1l);

        //修改客戶名稱

        customer.setCustName("傳智播客順義校區");

        //更新

        customerDao.save(customer);

    }
    
    @Test

    public void testCount() {
          long count = customerDao.count();
          System.out.println(count);
    }
    
    @Test

    public void testExits() {
          boolean exists = customerDao.exists((long) 2);
          
          System.out.println(exists);
    }
    
    
    
}

 

 

 

 
    @Test

    @Transactional
    public void testGetOne() {
          Customer one = customerDao.getOne((long) 2);
          
          System.out.println(one);
    }
    

 

getOne是懶加載,findOne是直接加載,懶加載的實現需要依賴事務,所有使用getOne方法的時候,一定要引入事務管理的依賴,這里使用 @Transactiona,否則代碼會報錯

3.2 使用JPQL的方式查詢
使用Spring Data JPA提供的查詢方法已經可以解決大部分的應用場景,但是對於某些業務來說,我們還需要靈活的構造查詢條件,這時就可以使用@Query注解,結合JPQL的語句方式完成查詢

 

 

package com.atguigu.springdata;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import antlr.collections.List;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
 
}

 

   //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

 

 2表示的是輸入參數為name,1表示輸入的參數是id

 

 

 此外,也可以通過使用 @Query 來執行一個更新操作,為此,我們需要在使用 @Query 的同時,用 @Modifying 來將該操作標識為修改查詢,這樣框架最終會生成一個更新的操作,而非查詢

package com.atguigu.springdata;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import antlr.collections.List;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")

    @Modifying

    public void updateCustomer(String custName,Long custId);
 
}

 

執行更新或者刪除操作,必須需要添加 @Modifying,此外必須要具有事務操作

@Test
    @Transactional
    @Rollback(value=false)
    public void testupdateCustomer() {
        customerDao.updateCustomer("我是可不2222", (long) 2);
    }
    

 

執行更新刪除操作需要有事務所有上面有@Transactional,此外jpa執行事務操作完成之后默認會回滾,當數據更新操作成功之后,因為jpa默認要回滾,會把更新的數據還原回去,我們要在數據庫中看到更新的

數據,我們要禁止jpa的回滾@Rollback(value=false)

 

 

3.3 使用SQL語句查詢
Spring Data JPA同樣也支持sql語句的查詢,如下:

 

 

 

 

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")
    @Modifying
    public void updateCustomer(String custName,Long custId);
 
    
    /**

     * nativeQuery : 使用本地sql的方式查詢

     */

    @Query(value="select * from cst_customer",nativeQuery=true)

    public List<Object[]> findSql();
    
}

 

這里千萬要注意返回的是一個List<Object[]>,每一個元素是一個Object類型的數組,不能寫成List<Customer[]>

@Test
    public void testfindSql() {
          List<Object[]> datas = customerDao.findSql();
          
          for(Object[] data:datas){
              
              System.out.println(Arrays.toString(data));
          }
          
    }

 

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")
    @Modifying
    public void updateCustomer(String custName,Long custId);
 
    
    /**

     * nativeQuery : 使用本地sql的方式查詢

     */

    @Query(value="select * from cst_customer",nativeQuery=true)

    public List<Object[]> findSql();
    
    
    @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
    public List<Object []> findSql2(String name);
    
}

 

測試代碼

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest {

    @Autowired
    private CustomerDao customerDao;
    
    @Test
    public  void testFind() {
        
      com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
      System.out.println(customer.toString());
    }
    
    /**

     * 保存客戶:調用save(obj)方法

     */

    @Test

    public void testSave() {

        Customer c = new Customer();

        c.setCustName("傳智播客");

        customerDao.save(c);

    }

   

    /**

     * 修改客戶:調用save(obj)方法

     *      對於save方法的解釋:如果執行此方法是對象中存在id屬性,即為更新操作會先根據id查詢,再更新   

     *                      如果執行此方法中對象中不存在id屬性,即為保存操作

     *         

     */

    @Test

    public void testUpdate() {

        //根據id查詢id為1的客戶

        Customer customer = customerDao.findOne(1l);

        //修改客戶名稱

        customer.setCustName("傳智播客順義校區");

        //更新

        customerDao.save(customer);

    }
    
    @Test

    public void testCount() {
          long count = customerDao.count();
          System.out.println(count);
    }
    
    @Test

    public void testExits() {
          boolean exists = customerDao.exists((long) 2);
          
          System.out.println(exists);
    }
    
    
    @Test

    @Transactional
    public void testGetOne() {
          Customer one = customerDao.getOne((long) 2);
          
          System.out.println(one);
    }
    
    @Test
    @Transactional
    @Rollback(value=false)
    public void testupdateCustomer() {
        customerDao.updateCustomer("我是可不2222", (long) 2);
    }
    
    @Test
    public void testfindSql() {
          List<Object[]> datas = customerDao.findSql();
          
          for(Object[] data:datas){
              
              System.out.println(Arrays.toString(data));
          }
          
    }
    
  //測試sql查詢
    @Test
    public void testFindSql()
    {

        List<Object[]> list = customerDao.findSql2("迅騰軟件%");//模糊查詢
        for(Object[] obj: list){

            System.out.println(Arrays.toString(obj));
        }
    }

    
}

 

3.4   方法命名規則查詢

顧名思義,方法命名規則查詢就是根據方法的名字,就能創建查詢。只需要按照Spring Data JPA提供的方法命名規則定義方法的名稱,就可以完成查詢工作。Spring Data JPA在程序執行的時候會根據方法名稱進行解析,並自動生成查詢語句進行查詢

 

按照Spring Data JPA 定義的規則,查詢方法以findBy開頭,涉及條件查詢時,條件的屬性用條件關鍵字連接,要注意的是:條件屬性首字母需大寫。框架在進行方法名解析時,會先把方法名多余的前綴截取掉,然后對剩下部分進行解析。

 

 

 

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")
    @Modifying
    public void updateCustomer(String custName,Long custId);
 
    
    /**

     * nativeQuery : 使用本地sql的方式查詢

     */

    @Query(value="select * from cst_customer",nativeQuery=true)

    public List<Object[]> findSql();
    
    
    @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
    public List<Object []> findSql2(String name);
    
    
    //方法命名方式查詢(根據客戶名稱查詢客戶)

    public Customer findByCustName(String custName);
    
}

 

測試代碼如下

 @Test
    public void testFindSql22()
    {

       Customer customer = customerDao.findByCustName("3333");
       System.out.println(customer.toString());
    }

 

 

 

 

 

 

 

 

 我們使用下Like查看下模糊查詢

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")
    @Modifying
    public void updateCustomer(String custName,Long custId);
 
    
    /**

     * nativeQuery : 使用本地sql的方式查詢

     */

    @Query(value="select * from cst_customer",nativeQuery=true)

    public List<Object[]> findSql();
    
    
    @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
    public List<Object []> findSql2(String name);
    
    
    //方法命名方式查詢(根據客戶名稱查詢客戶)

    public Customer findByCustName(String custName);
    
    public List<Customer> findByCustNameLike(String custName);
    
}

 

測試代碼如下

  
    @Test
    public void testFindSql22()
    {

       List<Customer> customers = customerDao.findByCustNameLike("3333%");
       for(Customer customer:customers){
           System.out.println(customer.toString());
       }
       
    }

 

 

 

 

 這里沒有占位符,兩個參數順利不能弄錯了

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
{
    


   

    //@Query 使用jpql的方式查詢。?1代表參數的占位符,其中1對應方法中的參數索引

    @Query(value="from Customer where custName = ?1")

    public Customer findCustomer(String custName);
    
    
    @Query(value="update Customer set custName = ?1 where custId = ?2")
    @Modifying
    public void updateCustomer(String custName,Long custId);
 
    
    /**

     * nativeQuery : 使用本地sql的方式查詢

     */

    @Query(value="select * from cst_customer",nativeQuery=true)

    public List<Object[]> findSql();
    
    
    @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
    public List<Object []> findSql2(String name);
    
    
    //方法命名方式查詢(根據客戶名稱查詢客戶)

    public Customer findByCustName(String custName);
    
    public List<Customer> findByCustNameLike(String custName);
    
    public List<Customer> findByCustNameLikeAndCusIndustry(String custName,String cusIndustry);
    
}

 

測試代碼如下

 @Test
    public void testFindSql22()
    {

       List<Customer> customers = customerDao.findByCustNameLikeAndCusIndustry("3333%","明星");
       for(Customer customer:customers){
           System.out.println(customer.toString());
       }
       
    }
Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_,
        customer0_.cust_industry as cust_ind2_0_,
        customer0_.cust_address as cust_add3_0_,
        customer0_.cust_level as cust_lev4_0_,
        customer0_.cust_name as cust_nam5_0_,
        customer0_.cust_phone as cust_pho6_0_,
        customer0_.cust_source as cust_sou7_0_ 
    from
        cst_customer customer0_ 
    where
        (
            customer0_.cust_name like ?
        ) 
        and customer0_.cust_industry=?

 

 

 我們重點來看下JpaSpecificationExecutor方法

 

 這個接口有上面的幾個方法,T findOne(Specification<T> spec);之前的JpaRepository接口也有findOne方法只能依據主鍵查詢,但是沒有攜帶Specification參數,這里攜帶了Specification參數

我們可以按照主鍵查詢,也可以安裝名稱查詢,我們可以自定義查詢條件

 

 

 

 

/**
 * Specification in the sense of Domain Driven Design.
 * 
 * @author Oliver Gierke
 * @author Thomas Darimont
 */
public interface Specification<T> {

    /**
     * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
     * {@link Root} and {@link CriteriaQuery}.
     * 
     * @param root
     * @param query
     * @return a {@link Predicate}, must not be {@literal null}.
     */
    Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}

 

我們來測試下上面的幾個接口

 

 

 

 對象CriteriaBuilder有下面這樣多的比較的方式

 

 

 

 

 @Test
    public void testFindSql223333()
    {

     Specification<Customer> spec = new Specification<Customer>() {

        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            // TODO Auto-generated method stub
            Path<Object> custName = root.get("custName");
            Predicate predicate = cb.equal(custName, "3333");
            return predicate;
        }
    };
       
     Customer customer = customerDao.findOne(spec);
     System.out.println(customer.toString());
    }

 

多個查詢條件的拼接

 

 

@Test
    public void testFindSql223333222()
    {

     Specification<Customer> spec = new Specification<Customer>() {

        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            // TODO Auto-generated method stub
            Path<Object> custName = root.get("custName");
            Path<Object> cusIndustry = root.get("cusIndustry");
            Predicate predicate1 = cb.equal(custName, "3333");
            Predicate predicate2 = cb.equal(cusIndustry, "2222");
            Predicate predicate3 = cb.and(predicate1,predicate2);
            return predicate3;
        }
    };
       
     Customer customer = customerDao.findOne(spec);
     System.out.println(customer.toString());
    }

 

 

 

 

 

@Test
    public void testFindSql223333222wwww()
    {

     Specification<Customer> spec = new Specification<Customer>() {

        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            // TODO Auto-generated method stub
            Path<Object> custName = root.get("custName");
            Predicate predicate = cb.like(custName.as(String.class), "33%");
            return predicate;
        }
    };
       
     List<Customer> customer = customerDao.findAll(spec);
     System.out.println(customer.toString());
    }

 

對於 List<Customer> customer = customerDao.findAll(spec)返回的數據是一個集合,我們可以指定返回的集合中的數據按照某種方式進行排序

 

 

 @Test
    public void testFindSql223333222wwwwww()
    {

     Specification<Customer> spec = new Specification<Customer>() {

        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            // TODO Auto-generated method stub
            Path<Object> custName = root.get("custName");
            Predicate predicate = cb.like(custName.as(String.class), "33%");
            return predicate;
        }
    };
       
    Sort sort = new Sort(Sort.Direction.ASC,"custId");
     List<Customer> customer = customerDao.findAll(spec,sort);
     System.out.println(customer.toString());
    }

 

按照"custId"的Sort.Direction.ASC進行排序

 

 

 

    /**
     * 目標: 實現帶查詢條件的分頁. id > 5 的條件
     * 
     * 調用 JpaSpecificationExecutor 的 Page<T> findAll(Specification<T> spec, Pageable pageable);
     * Specification: 封裝了 JPA Criteria 查詢的查詢條件
     * Pageable: 封裝了請求分頁的信息: 例如 pageNo, pageSize, Sort
     */
    @Test
    public void testJpaSpecificationExecutorss(){
        int pageNo = 3 - 1;
        int pageSize = 5;
        Sort sort = new Sort(Sort.Direction.ASC,"custId");
        //封裝分頁的信息
        PageRequest pageable = new PageRequest(pageNo, pageSize,sort);
        
         Specification<Customer> spec = new Specification<Customer>() {

                public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    // TODO Auto-generated method stub
                    Path<Object> custName = root.get("custName");
                    Predicate predicate = cb.like(custName.as(String.class), "33%");
                    return predicate;
                }
            };
               
            
        
        Page<Customer> page = customerDao.findAll(spec, pageable);
        
        System.out.println("總記錄數: " + page.getTotalElements());
        System.out.println("當前第幾頁: " + (page.getNumber() + 1));
        System.out.println("總頁數: " + page.getTotalPages());
        System.out.println("當前頁面的 List: " + page.getContent());
        List<Customer> content = page.getContent();
        System.out.println("當前頁面的記錄數: " + page.getNumberOfElements());
        /*List<Person> collect = page.getContent().stream().map(stat->(Person)stat).collect(Collectors.toList());
        System.out.println("當前頁面的 List1: " + collect);*/
    }

 

打印結果如下

Hibernate: 
    select
        count(customer0_.cust_id) as col_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_name like ?
總記錄數: 1
當前第幾頁: 3
總頁數: 1
當前頁面的 List: []
當前頁面的記錄數: 0

 

 

 

 

 

 

 

 

 客戶個聯系人是一對多的關系

 

 

 

 

 

 

 

 

 

3.2 實戰Hibernate一對多關聯映射
3.2.1 創建數據表(客戶----聯系人)
客戶表:

CREATE TABLE `cst_customer` (

  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',

  `cust_name` varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)',

  `cust_source` varchar(32) DEFAULT NULL COMMENT '客戶信息來源',

  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客戶所屬行業',

  `cust_level` varchar(32) DEFAULT NULL COMMENT '客戶級別',

  `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定電話',

  `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移動電話',

  PRIMARY KEY (`cust_id`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

 

聯系人表:

CREATE TABLE `cst_linkman` (

  `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '聯系人編號(主鍵)',

  `lkm_name` varchar(16) DEFAULT NULL COMMENT '聯系人姓名',

  `lkm_cust_id` bigint(32) DEFAULT NULL COMMENT '客戶id',

  `lkm_gender` char(1) DEFAULT NULL COMMENT '聯系人性別',

  `lkm_phone` varchar(16) DEFAULT NULL COMMENT '聯系人辦公電話',

  `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '聯系人手機',

  `lkm_email` varchar(64) DEFAULT NULL COMMENT '聯系人郵箱',

  `lkm_qq` varchar(16) DEFAULT NULL COMMENT '聯系人qq',

  `lkm_position` varchar(16) DEFAULT NULL COMMENT '聯系人職位',

  `lkm_memo` varchar(512) DEFAULT NULL COMMENT '聯系人備注',

  PRIMARY KEY (`lkm_id`),

  KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),

  CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

 

 

 

接下來我們要新增一個聯系人的實體類對象

在customer客戶端實體類中,需要配置下面的信息

 

 

 

package com.atguigu.springdata;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity // 聲明此類是個實體類 需要導入javax.persistence.Entity;

@Table(name = "cst_customer") //需要將該類對應到數據庫中的哪一個表中,name中填表的名稱

public class Customer {



@Id //聲明主鍵 

@GeneratedValue(strategy = GenerationType.IDENTITY) //聲明主鍵的生成策略為自動遞增

//mysql使用自增模式,orcle 使用序列模式

@Column(name = "cust_id") //設置該屬性和數據庫中的哪一個字段對應

private Long custId;

 

@Column(name = "cust_name")

private String custName;

 

@Column(name = "cust_source")

private String custSource;

 

@Column(name = "cust_level")

private String custLevel;

 

@Column(name = "cust_industry")

private String cusIndustry;

 

@Column(name = "cust_phone")

private String custPhone;

 

@Column(name = "cust_address")

private String custAddress;


@OneToMany(targetEntity=LinkMan.class) @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id") private Set<LinkMan> linkMans = new HashSet<LinkMan>(); public Long getCustId() {

return custId;

}



public void setCustId(Long custId) {

this.custId = custId;

}



public String getCustName() {

return custName;

}



public void setCustName(String custName) {

this.custName = custName;

}



public String getCustSource() {

return custSource;

}



public void setCustSource(String custSource) {

this.custSource = custSource;

}



public String getCustLevel() {

return custLevel;

}



public void setCustLevel(String custLevel) {

this.custLevel = custLevel;

}



public String getCusIndustry() {

return cusIndustry;

}



public void setCusIndustry(String cusIndustry) {

this.cusIndustry = cusIndustry;

}



public String getCustPhone() {

return custPhone;

}



public void setCustPhone(String custPhone) {

this.custPhone = custPhone;

}



public String getCustAddress() {

return custAddress;

}



public void setCustAddress(String custAddress) {

this.custAddress = custAddress;

}



@Override

public String toString() {

return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource

+ ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone

+ ", custAddress=" + custAddress + "]";

}



public Set<LinkMan> getLinkMans() {
    return linkMans;
}



public void setLinkMans(Set<LinkMan> linkMans) {
    this.linkMans = linkMans;
}

 

}

 

在聯系人方需要配置如下

 

 

 

package com.atguigu.springdata;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity // 聲明此類是個實體類 需要導入javax.persistence.Entity;

@Table(name = "cst_linkman") //需要將該類對應到數據庫中的哪一個表中,name中填表的名稱
public class LinkMan {

@Id //聲明主鍵
@GeneratedValue(strategy = GenerationType.IDENTITY) //聲明主鍵的生成策略為自動遞增
@Column(name = "lkm_id") //設置該屬性和數據庫中的哪一個字段對應


private Long lkmId; @Column(name = "lkm_gender") //設置該屬性和數據庫中的哪一個字段對應 private Character lkmGender; @Column(name = "lkm_name") //設置該屬性和數據庫中的哪一個字段對應 private String lkmName; @Column(name = "lkm_phone") //設置該屬性和數據庫中的哪一個字段對應 private String lkmPhone; @Column(name = "lkm_email") //設置該屬性和數據庫中的哪一個字段對應 private String lkmEmail; @Column(name = "lkm_qq") //設置該屬性和數據庫中的哪一個字段對應 private String lkmQq; @Column(name = "lkm_mobile") //設置該屬性和數據庫中的哪一個字段對應 private String lkmMobile; @Column(name = "lkm_memo") //設置該屬性和數據庫中的哪一個字段對應 private String lkmMemo; @Column(name = "lkm_position") //設置該屬性和數據庫中的哪一個字段對應 private String lkmPosition; @ManyToOne(targetEntity=Customer.class) @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id") private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Long getLkmId() { return lkmId; } public void setLkmId(Long lkmId) { this.lkmId = lkmId; } public Character getLkmGender() { return lkmGender; } public void setLkmGender(Character lkmGender) { this.lkmGender = lkmGender; } public String getLkmName() { return lkmName; } public void setLkmName(String lkmName) { this.lkmName = lkmName; } public String getLkmPhone() { return lkmPhone; } public void setLkmPhone(String lkmPhone) { this.lkmPhone = lkmPhone; } public String getLkmEmail() { return lkmEmail; } public void setLkmEmail(String lkmEmail) { this.lkmEmail = lkmEmail; } public String getLkmQq() { return lkmQq; } public void setLkmQq(String lkmQq) { this.lkmQq = lkmQq; } public String getLkmMobile() { return lkmMobile; } public void setLkmMobile(String lkmMobile) { this.lkmMobile = lkmMobile; } public String getLkmMemo() { return lkmMemo; } public void setLkmMemo(String lkmMemo) { this.lkmMemo = lkmMemo; } public String getLkmPosition() { return lkmPosition; } public void setLkmPosition(String lkmPosition) { this.lkmPosition = lkmPosition; } }

 

  @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")中表示的是表聯系人中的lkm_cust_id字段的值,來自於表客戶的cust_id

 

接下來,我們要編寫一個操作聯系人的接口類

package com.atguigu.springdata;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/*
* 符合SpringDatajpa的dao層接口規范
*JpaRepository<操作的實體類類型,實體類中主鍵屬性的類型>
    *封裝了基本的CRUD操作
 JpaSpecificationExecutor<操作的實體類類型>
    *封裝了復雜查詢操作(分頁)
* */
 

public interface LinnkManDao  extends JpaRepository<LinkMan,Long>, JpaSpecificationExecutor<LinkMan> 
{
    


   

}

 

整個工程的結構如下所示

 

 

 接下來我們來就可以進行測試了

 

 

 我們來看下程序的代碼

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.atguigu.springdata.LinkMan;
import com.atguigu.springdata.LinnkManDao;
import com.itcast.utils.JpaUtils;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class oneToManyTest {

    @Autowired
    private CustomerDao customerDao;
    
    
    @Autowired
    private LinnkManDao linnkManDao;
    
   
    @Test
    @Transactional
    @Rollback(value=false)
    public void save(){
        
        Customer customer = new Customer();
        customer.setCustName("百度");
        
        LinkMan linkMan = new LinkMan();
        linkMan.setLkmName("小明");
        linkMan.setCustomer(customer);
        
        customerDao.save(customer);
        
        linnkManDao.save(linkMan);
        
    }

}

 

這里操作了兩張表要保證事務的一致性 @Transactional,其次事務操作成功之后要讓更新的記錄保存到數據庫,不進行回滾  @Rollback(value=false)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM