自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringBoot 整合 JPA 輕松搞定數(shù)據(jù)表增刪改查!

數(shù)據(jù)庫 其他數(shù)據(jù)庫
為了解決重復(fù)的編寫數(shù)據(jù)操作語句,開發(fā)社區(qū)誕生了許多優(yōu)秀的 ORM 框架,比如 Hibernate、OpenJPA、TopLink 等,其中 Hibernate 相對較為知名,在 Hibernate 框架的幫助下,開發(fā)者可以輕松的以操作 Java 實體的方式來完成對數(shù)據(jù)表的“增刪改查”操作,能極大的簡化代碼編寫的工作量。

01、背景介紹

在之前的文章中,我們介紹了通過JdbcTemplate來實現(xiàn)數(shù)據(jù)庫的訪問和讀寫操作。當(dāng)有一定的開發(fā)經(jīng)驗之后,你會發(fā)現(xiàn)所有涉及到數(shù)據(jù)庫操作的代碼,除了表名和字段不同外,操作的語句基本都類似,功能上可以統(tǒng)一歸納為“增、刪、改、查”,編寫大量這種類似的代碼,對于開發(fā)者來說,其實非??菰铩?/p>

為了解決重復(fù)的編寫數(shù)據(jù)操作語句,開發(fā)社區(qū)誕生了許多優(yōu)秀的 ORM 框架,比如 Hibernate、OpenJPA、TopLink 等,其中 Hibernate 相對較為知名,在 Hibernate 框架的幫助下,開發(fā)者可以輕松的以操作 Java 實體的方式來完成對數(shù)據(jù)表的“增刪改查”操作,能極大的簡化代碼編寫的工作量。

國內(nèi)外有不少的項目基于 Spring Boot JPA 來完成對數(shù)據(jù)庫的操作訪問,那么 Spring Boot JPA 和 ORM 框架之間有著怎樣的關(guān)系呢?

簡單的說,Spring Boot JPA 是 Spring 在 ORM 框架的基礎(chǔ)上封裝的一套 JPA 應(yīng)用框架,具體的數(shù)據(jù)訪問和操作實現(xiàn)還是依賴于 ORM 框架來完成,Spring Boot JPA 只是完成了接口操作的標(biāo)準(zhǔn)封裝,包括增刪改查等在內(nèi)的常用功能,可以幫助開發(fā)者降低學(xué)習(xí)成本,同時極大的提升開發(fā)效率。

值得一提的是:JPA (Java Persistence API) 是 Sun 官方提出的一套 Java 數(shù)據(jù)持久化操作的規(guī)范,不是一套產(chǎn)品,像上文說的 Hibernate,OpenJPA,TopLink 等,可以理解成 JPA 的具體產(chǎn)品實現(xiàn)。

以 Spring Boot 的2.0版本為例,Spring Boot JPA 的底層依賴于 Hibernate 框架來完成數(shù)據(jù)庫的訪問和操作,如果你熟悉 Hibernate 的框架使用,那么可以輕松的上手并使用它。

下面我們一起來看看 Spring Boot JPA 的具體使用姿勢。

02、應(yīng)用實踐

2.1、工程配置

首先在pom.xml文件中添加相關(guān)的依賴包。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

然后在application.properties文件中配置相關(guān)的數(shù)據(jù)源訪問地址,以及相關(guān)hibernate屬性配置。

# 數(shù)據(jù)源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# hibernate信息配置
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true

其中spring.jpa.properties.hibernate.hbm2ddl.auto參數(shù)是hibernate的一個配置屬性,主要作用有:自動創(chuàng)建、更新、驗證數(shù)據(jù)庫表結(jié)構(gòu)。

相關(guān)的可選參數(shù)如下:

  • create:每次加載 hibernate 相關(guān)實體表時會刪除上一次生成的表,然后按照最新的 model 類生成新表,會造成數(shù)據(jù)庫表數(shù)據(jù)丟失;
  • create-drop:每次加載 hibernate 時會根據(jù) model 類生成新表,當(dāng)服務(wù)關(guān)閉時,表自動刪除,通常用于測試;
  • update:常用屬性,第一次加載 hibernate 時會根據(jù) model 類自動建表,以后加載 hibernate 時根據(jù) model 類自動更新表結(jié)構(gòu),但是不會刪除表中的數(shù)據(jù);
  • validate:每次加載 hibernate 時會驗證數(shù)據(jù)庫表的結(jié)構(gòu),只會和數(shù)據(jù)庫中的表進(jìn)行比較,不會創(chuàng)建新表,但是會插入新值;

其次,spring.jpa.properties.hibernate.dialect參數(shù)主要用于指定生成表名時的存儲引擎為 InnoDBD,如果不配置,默認(rèn)是MylSAM;spring.jpa.show-sql參數(shù)用于打印出自動生成的 SQL,方便調(diào)試。

2.2、基本增刪改查操作

下面我們一起來體驗一下 JPA 中常用的增刪改查操作。

2.2.1、創(chuàng)建實體

創(chuàng)建一個Student實體,包含三個屬性,表名為tb_student,當(dāng)加載 hibernate 的時候會自動創(chuàng)建到數(shù)據(jù)庫中,代碼如下:

@Entity
@Table(name = "tb_student")
public class Student {

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false, unique = true)
    private String name;

    @Column(nullable = false)
    private Integer age;

    // set、get方法等...
}
  • @Entity注解用于標(biāo)識Student類是一個持久化的實體類;
  • @Table注解用于標(biāo)識Student類映射到數(shù)據(jù)庫中的表名稱;
  • @Id注解用于標(biāo)識Student映射到數(shù)據(jù)庫的主鍵字段
  • @GeneratedValue注解用于標(biāo)識Student映射到數(shù)據(jù)庫的主鍵為自增類型
  • @Column注解用于標(biāo)識Student映射到數(shù)據(jù)庫的字段相關(guān)信息

2.2.2、創(chuàng)建數(shù)據(jù)訪問接口

針對Student實體類,創(chuàng)建一個對應(yīng)的JpaRepository接口,用于實現(xiàn)對實體的數(shù)據(jù)訪問和操作,代碼如下:

public interface StudentRepository extends JpaRepository<Student,Long> {

}

其中JpaRepository接口已經(jīng)封裝好了常用的增刪改查方法邏輯,使用者只需要調(diào)用相關(guān)的方法接口實現(xiàn)對數(shù)據(jù)庫表的操作。

JpaRepository接口封裝的部分方法,源碼如下圖!

圖片圖片

2.2.3、單元測試

完成以上的實體創(chuàng)建和數(shù)據(jù)訪問接口的編寫之后,下面我們編寫對應(yīng)的單元測試類來驗證一下編寫的內(nèi)容是否正確,代碼如下:

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

    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void test(){
        // 插入3條數(shù)據(jù)
        studentRepository.save(new Student("張三", 20));
        studentRepository.save(new Student("李四", 21));
        studentRepository.save(new Student("王五", 22));

        // 查詢?nèi)繑?shù)據(jù)
        List<Student> dbList = studentRepository.findAll();
        System.out.println("第一次全量查詢結(jié)果:" + dbList.toString());

        System.out.println("------------------------");

        // 修改數(shù)據(jù)
        studentRepository.save(new Student(dbList.get(0).getId(),"趙六", 20));

        // 查詢指定數(shù)據(jù)
        Optional<Student> findResult = studentRepository.findById(dbList.get(0).getId());
        System.out.println("查詢第一條數(shù)據(jù)結(jié)果:" + findResult.toString());

        System.out.println("-----------------");

        // 刪除數(shù)據(jù)
        studentRepository.deleteById(dbList.get(0).getId());

        // 查詢?nèi)繑?shù)據(jù)
        List<Student> result = studentRepository.findAll();
        System.out.println("第二次全量查詢結(jié)果:" + result.toString());
    }
}

運行單元測試,輸出結(jié)果如下!

第一次全量查詢結(jié)果:[Student{id=1, name='張三', age=20}, Student{id=2, name='李四', age=21}, Student{id=3, name='王五', age=22}]
------------------------
查詢第一條數(shù)據(jù)結(jié)果:Optional[Student{id=1, name='趙六', age=20}]
------------------------
第二次全量查詢結(jié)果:[Student{id=2, name='李四', age=21}, Student{id=3, name='王五', age=22}]

2.3、自定義簡單查詢操作

Spring Boot JPA 不僅為開發(fā)者封裝了常用的模板方法,還支持根據(jù)方法名來動態(tài)生成 SQL 語句,比如findByXX,countByXX,getByXX后面跟屬性名稱,當(dāng)調(diào)用方法的時候會自動生成響應(yīng)的 SQL 語句,具體示例如下:

public interface StudentRepository extends JpaRepository<Student,Long> {

    /**
     * 自定義簡單查詢,通過姓名進(jìn)行搜索
     * @param name
     * @return
     */
    Student findByName(String name);

    /**
     * 自定義簡單查詢,通過姓名和年齡進(jìn)行統(tǒng)計
     * @param name
     * @return
     */
    Integer countByNameAndAge(String name, Integer age);
}

編寫單元測試驗證內(nèi)容的正確性。

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

    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void simpleTest(){
        Student result1 = studentRepository.findByName("李四");
        System.out.println("第一次查詢結(jié)果:" + result1.toString());

        System.out.println("-----------------");

        Integer result2 = studentRepository.countByNameAndAge("王五", 22);
        System.out.println("第二次查詢結(jié)果:" + result2);
    }
}

輸出結(jié)果如下!

第一次查詢結(jié)果:Student{id=2, name='李四', age=21}
-----------------
第二次查詢結(jié)果:1

方法上支持 SQL 語句中的關(guān)鍵字,比如And、Or、Like、OrderBy等。

具體關(guān)鍵字上的使用和生成的 SQL 對應(yīng)的關(guān)系如下:

圖片圖片

更多的關(guān)鍵字使用可以參閱官方文檔。

2.4、復(fù)雜查詢操作

在實際的開發(fā)過程中,由于業(yè)務(wù)的需要,我們經(jīng)常需要編寫復(fù)雜的 SQL 語句,比如鏈表查詢,分頁查詢等,這個時候就需要用到自定義 SQL 語句的操作了。

2.4.1、自定義 SQL 查詢

其實大部分的 SQL 語句都可以通過方法來動態(tài)生成,如果想自定義 SQL 查詢,Spring Boot JPA 也是支持的,操作上很簡單。

在接口方法上,添加@Query注解,即可實現(xiàn)自定義 SQL 語句;如果涉及到新增、修改和刪除操作,需要再加上@Modifying注解,同時也需要添加@Transactional注解事務(wù)支持。

具體示例如下:

public interface StudentRepository extends JpaRepository<Student,Long> {

    /**
     * 自定義SQL語句,單條查詢
     * @param studentName
     * @return
     */
    @Query(value = "select s from Student s where s.name = ?1")
    Student findByStudentName(String studentName);

    /**
     * 自定義SQL語句,修改數(shù)據(jù)
     * @param name
     * @param age
     * @return
     */
    @Transactional
    @Modifying
    @Query(value = "update Student s set s.age = ?2 where s.name = ?1")
    int updateAgeByName(String name, Integer age);

    /**
     * 自定義SQL語句,刪除數(shù)據(jù)
     * @param name
     */
    @Transactional
    @Modifying
    @Query(value = "delete from Student s where s.name = ?1")
    int deleteByName(String name);
}

編寫單元測試驗證內(nèi)容的正確性。

@Test
public void sqlTest(){

    // 新增
    studentRepository.save(new Student("王五", 22));

    // 查詢
    Student result1 = studentRepository.findByStudentName("王五");
    System.out.println("第一次查詢結(jié)果:" + result1.toString());

    System.out.println("-----------------");

    // 修改
    studentRepository.updateAgeByName("王五", 30);

    Student result2 = studentRepository.findByStudentName("王五");
    System.out.println("第二次查詢結(jié)果:" + result2.toString());

    System.out.println("-----------------");

    // 刪除
    studentRepository.deleteByName("王五");

    Student result3 = studentRepository.findByStudentName("王五");
    System.out.println("第三次查詢結(jié)果:" + result3);
}

輸出結(jié)果如下!

第一次查詢結(jié)果:Student{id=4, name='王五', age=22}
-----------------
第二次查詢結(jié)果:Student{id=4, name='王五', age=30}
-----------------
第三次查詢結(jié)果:null

值得注意的是:這里自定義的 SQL 語句并非數(shù)據(jù)庫中的 SQL 語句,而是 hibernate 所支持 SQL 語句,簡稱 hsql,例如表名要采用 Java 實體而非數(shù)據(jù)庫中真實的表名,否則可能會報錯。

2.4.2、分頁查詢

分頁查詢,在實際的業(yè)務(wù)開發(fā)中非常常見,其實 Spring Boot JPA 已經(jīng)幫助開發(fā)者封裝了分頁查詢的方法邏輯,在查詢的時候傳入Pageable參數(shù)即可。

示例如下:

@Test
public void pageTest(){
    // 構(gòu)建分頁參數(shù)
    int page=0,size=10;
    Sort sort = new Sort(Sort.Direction.DESC, "id");
    Pageable pageable = PageRequest.of(page, size, sort);

    // 構(gòu)建單條件查詢參數(shù)
    Student param = new Student();
    param.setAge(21);
    Example<Student> example = Example.of(param);

    // 發(fā)起分頁查詢
    Page<Student> result = studentRepository.findAll(example, pageable);
    System.out.println("查詢結(jié)果,總行數(shù):" + result.getTotalElements());
    System.out.println("查詢結(jié)果,明細(xì):" + result.getContent());
}

輸出結(jié)果如下:

查詢結(jié)果,總行數(shù):1
查詢結(jié)果,明細(xì):[Student{id=2, name='李四', age=21}]

當(dāng)然我們也可以根據(jù)自定義簡單查詢來實現(xiàn)分頁查詢,在 JPA 的幫助下動態(tài)生成 SQL 語句,示例如下:

public interface StudentRepository extends JpaRepository<Student,Long> {

    /**
     * 自定義簡單查詢,通過年齡進(jìn)行分頁搜索
     * @param age
     * @param pageable
     * @return
     */
    Page<Student> findByAge(Integer age, Pageable pageable);
}

值得注意的是:自定義的方法不會自動進(jìn)行count語句匯總查詢,推薦采用模板方法來進(jìn)行分頁查詢。

2.4.3、多表查詢

多表查詢,也是實際開發(fā)中經(jīng)常會碰到的場景,Spring Boot JPA 提供了兩種實現(xiàn)方式,第一種是利用 Hibernate 的級聯(lián)查詢來實現(xiàn),第二種是自定義 SQL 語句來實現(xiàn)。

第一種就不多說了,主要通過@OneToOne、@OneToMany、@ManyToOne、@ManyToMany和@JoinTable注解來完成多表的級聯(lián)查詢,不過這種方式需要在數(shù)據(jù)庫層面建立外鍵關(guān)聯(lián),通過外鍵來完成級聯(lián)查詢,不推薦采用。

下面我們來介紹一下自定義 SQL 語句來實現(xiàn),實現(xiàn)起來也很簡單,示例如下:

public interface TeacherRepository extends JpaRepository<Teacher,Long> {

    /**
     * 自定義鏈表查詢
     * @return
     */
    @Query(value = "select s.id, s.name, t.teacher_id as teacherId, t.teacher_name as teacherName from tb_student s left join tb_teacher t on s.teacher_id = t.teacher_id ", nativeQuery = true)
    List<Map<String,Object>> findCustomer();
}

編寫單元測試,驗證代碼的正確性。

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

    @Autowired
    private TeacherRepository teacherRepository;

    @Test
    public void test2(){
        // 查詢?nèi)繑?shù)據(jù)
        List<Map<String,Object>> dbList = teacherRepository.findCustomer();
        System.out.println("查詢結(jié)果:" + JSONObject.toJSONString(dbList));
    }
}

輸出結(jié)果如下:

查詢結(jié)果:[{"id":9,"teacherId":1,"name":"李1","teacherName":"張老師"},{"name":"李2","id":10,"teacherId":1,"teacherName":"張老師"},{"id":11,"name":"李3","teacherId":1,"teacherName":"張老師"}]

直接編寫 sql 語句,非常簡單靈活。

2.5、屬性映射屏蔽操作

如果某個實體類中的屬性,不想被映射到數(shù)據(jù)庫,可以添加@Transient注解來實現(xiàn),示例如下。

@Transient
private String  name;


03、參考

1、http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html

責(zé)任編輯:武曉燕 來源: 潘志的研發(fā)筆記
相關(guān)推薦

2024-09-02 09:26:28

2024-07-17 08:29:20

2023-11-13 08:16:08

MySQL數(shù)據(jù)數(shù)據(jù)庫

2019-07-09 08:23:07

數(shù)據(jù)安全旅游網(wǎng)絡(luò)安全

2024-12-27 08:39:10

2024-09-09 16:50:21

2021-10-20 09:04:21

Spring Beanscope數(shù)據(jù)庫

2019-11-07 15:39:36

數(shù)據(jù)庫MySQL文章

2021-07-05 09:24:06

MySQL SQL 語句數(shù)據(jù)庫

2016-04-29 10:02:39

2024-11-14 10:38:43

2023-02-27 07:37:56

Curl操作SQL

2024-06-20 08:26:01

JPA公共字段

2012-04-19 10:06:16

ibmdw

2016-09-09 01:07:06

數(shù)據(jù)中心容量規(guī)劃數(shù)據(jù)中心

2024-11-18 00:22:34

2012-04-12 09:23:15

達(dá)夢數(shù)據(jù)庫

2009-11-13 15:54:26

ADO.NET數(shù)據(jù)庫操

2023-06-08 08:13:43

2020-05-13 09:14:16

哈希表數(shù)據(jù)結(jié)構(gòu)
點贊
收藏

51CTO技術(shù)棧公眾號