Spring JPA學習筆記

什麼是JPA?

什麼是JDBC知道吧?數據庫有Mysql,SQL Server,Oracle,Java爲了統一的去操做創建鏈接,JDBC出現了,有了JDBC,加載註冊不一樣的數據庫驅動就完事了。mysql

可是,JDBC好繁瑣的啊,每次都要寫一堆,煩人,因此一些框架出現了,例如Hibernate,TopLink,可是這些框架也是各類各樣的,我每次使用都要按照各自的框架來寫,這不行,爲了省事,JPA出現了spring

JPA是規範 JPA不是框架,沒有實現的方法,就是規範,提供了一些API接口,大家這些hibernate,TopLink框架啥的,遵循個人JPA規範就成sql

順便一提,JPA是Hibernate做者搞出來的,因此JPA和Hibernate同樣,不須要你寫SQL,有時候必須本身寫SQL可使用JPQL數據庫

PS:EJB有三種,分別是會話Bean(Session Bean),實體Bean(Entity Bean)和消息驅動Bean(MessageDriven Bean)。在EJB3.0推出之後,實體Bean被單獨分了出來,造成了新的規範JPA性能優化

引入配置

想要使用JPA,就要引入一些配置,個人項目是SpringBoot,其餘的框架也行,引入了三個,JPA,Hibernate,MySQL服務器

<!--JPA,我用的是SpringBoot的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <!--Hibernate,說了JPA只是一個規範,咱們使用Hibernate做爲實現-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
        <!--數據庫不能少-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

引入的配置完了,接下來是對JPA的一些配置,不能不寫,不寫不成功session

### Java Persistence Api --  Spring jpa 的配置信息
#其實這個hibernate.hbm2ddl.auto參數的做用主要用於:自動建立|更新|驗證數據庫表結構,有四個值
#create: 每次加載hibernate時都會刪除上一次的生成的表,而後根據你的model類再從新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是致使數據庫表數據丟失的一個重要緣由。
#create-drop :每次加載hibernate時根據model類生成表,可是sessionFactory一關閉,表就自動刪除。
#update:最經常使用的屬性,第一次加載hibernate時根據model類會自動創建起表的結構(前提是先創建好數據庫),之後加載hibernate時根據 model類自動更新表結構,即便表結構改變了但表中的行仍然存在不會刪除之前的行。要注意的是當部署到服務器後,表結構是不會被立刻創建起來的,是要等 應用第一次運行起來後纔會。
#validate :每次加載hibernate時,驗證建立數據庫表結構,只會和數據庫中的表進行比較,不會建立新表,可是會插入新值。
#dialect 主要是指定生成表名的存儲引擎爲InneoDB
#show-sql 是否打印出自動生產的SQL,方便調試的時候查看

spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true

這個是application.properties裏面關於JPA的配置,數據庫配置就不貼了,JPA配置的講解見註釋app

新建一個Entity Bean類

package com.cache.entity;

import javax.persistence.*;

@Entity
@Table(name="product")
public class Product {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Integer id;
    private String name;
    private Double price;
    private String type;

    public Product() {
    }

    public Product(Integer id, String name, Double price, String type) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.type = type;
    }

    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 Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                '}';
    }
}

這個爲啥叫Entity Bean類呢?我講一下,普通的Java Bean類加上@Entity註解以後就變成了Entity Bean類,這個Entity Bean的意思就是這個類能夠映射到數據庫框架

講解一下上面Entity Bean裏面的註解是什麼意思

@Entity : 這個註解表明這個Userinfo是一個實體類,也就是說,當你建立實體類時,須要加上@Entity 標誌着此類是實體類;
@Table(name=」userinfos」) :這個註解表明對應表的名稱,userinfos就是利用jpa要生成的表名稱;
@id :代表此屬性是主鍵;
@GeneratedValue :表示的是 主鍵生成策略,默認主鍵是自增加的,固然你也可使用 uuid
@Column :代表此屬性在數據庫中對應的字段,若是實體中的屬性與數據庫中的字段同樣,能夠省略不寫。

還有兩個註解我沒使用,能夠了解一下:

@Transient:Entity Bean的屬性或字段加上這個註解,該字段便不會映射到數據庫表

@Temporal:也是在Entity Bean的屬性或字段上加的,這個是對Date時間類型的精度的一個選擇,例如生日我就想精確到年月日就好了,下單時間我卻想精確到時分秒,這個時候就可使用這個,有Date,TIMESTAMP,TIME這三種精度

怎麼樣?爽不爽?沒有JDBC的繁瑣,我僅僅是寫了一個Entity Bean實體類,我就和數據庫進行映射關係了,內存中的實體類對象映射到數據庫了,這也叫持久化。

持久化是位於 JDBC 之上的一個更高層抽象。持久層將對象映射到數據庫,以便在查詢、 裝載、 更新, 或刪除對象的時候, 無須使用像 JDBC 那樣繁瑣的 API。

JPA的增刪改查

新建操做接口

使用Entity Bean實體類,咱們已經映射出了一個數據庫表,如今要存儲數據了,咱們須要新建一個接口

package com.cache.repository;

import com.cache.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import javax.transaction.Transactional;

public interface ProductRepository extends JpaRepository<Product,Integer> {

    //因爲JPA沒有更新方法,因此須要本身寫更新方法,我這裏只寫一個更新name的方法,若是想更新所有,能夠第一個參數寫類
    @Transactional
    @Modifying
    @Query("update Product set  name=?1 where id=?2")
    int updateNameById(String name,Integer id);
}

我來好好的講解一下這個接口,首先ProductRepository這個接口繼承了

JpaRepository這個類,這個類裏面有JPA的操做方法,因此只要咱們的接口繼承了這個類,咱們也就有方法能夠調用了,不須要本身寫。

可是,JPA只有正刪查,沒有更改的方法,因此咱們能夠在接口裏面本身寫,我就寫了一個更新Product實體類的name屬性的方法

@Transactional 開啓事務
@Modifying 修改方法專用註解
這兩個註解
@Query(「update Product set name=?1 where id=?2」)
此註解書寫JPql語句 其中 Product 是實體類名,name和 id 是實體類的屬性名,?1表明是第一個參數 ?2是第二個參數

注意:JPql裏面必須是實體類的類名,可不是你的數據庫表名,若是寫錯了會報 XXX is not mapped 錯誤

新建測試類

在咱們的ProductRepository接口上新建一個測試類,這個步驟不會的就太菜了

我直接貼出代碼了,我已經寫好了增刪改查的代碼了

package com.cache.repository;

import com.cache.entity.Product;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Optional;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductRepositoryTest {

    @Autowired
    private ProductRepository productRepository;

    //增長數據
    @Test
    public void save(){
        Product product=new Product();
        product.setId(1);
        product.setName("魅族16s");
        product.setPrice(2899.0);
        product.setType("手機類");
        //調用save方法保存一個對象的時候,會返回該對象
        Product p=productRepository.save(product);
        //斷言返回對象的值就是咱們存進去的值
        Assert.assertEquals(p.getName(),"魅族16s");
    }

    //刪除一個數據
    @Test
    public void delete(){
        productRepository.deleteById(1);
    }

    //更新,使用的是咱們本身寫的更新name方法
    @Test
    public void update(){
        productRepository.updateNameById("魅族16s Plus",2);
    }

    //查找數據
    @Test
    public void selectAll(){
        List<Product> lists=productRepository.findAll();
        for (Product product : lists) {
            System.out.println(product);
        }
    }
    @Test
    public void selectOne(){
        Optional<Product> product=productRepository.findById(2);
        System.out.println(product);
    }

}

我都執行了一遍,都是ok的

總結

因爲JPA是Hibernate實現的,因此不須要咱們寫SQL,都是自動的(除了JPQL)

簡單的說,JPA對比Mybatis,仍是簡單的不少,沒有配置文件了,不須要本身寫SQL了,連操做方法都有JpaRepository類幫咱們寫好了

若是不是須要性能優化什麼的,簡單的使用來講,仍是JPA好用

相關文章
相關標籤/搜索