Spring Boot 學習筆記(1.2):如何在 Spring Boot 項目中使用 Mysql

jopen 8年前發布 | 87K 次閱讀 MySQL Spring JEE框架 Spring Boot

本系列:

Spring Boot大大簡化了持久化任務,幾乎不需要寫SQL語句,之前我寫過一篇關于Mongodb的—— RESTful:Spring Boot with Mongodb

本文將會演示如何在Spring Boot項目中使用mysql數據庫。

1.建立數據庫連接(database connection)

在上篇文章中我們新建了一個Spring Boot應用程序,添加了jdbc和data-jpa等starters,以及一個h2數據庫依賴,這里我們將配置一個H2數據庫。

對于H2、HSQL或者Derby這類嵌入型數據庫,只要在pom文件中添加對應的依賴就可以,不需要額外的配置。當spring boot在classpath下發現某個數據庫依賴存在且在代碼中有關于 Datasource Bean 的定義時,就會自動創建一個數據庫連接。我們通過修改之前的bookpub程序說明這個問題,需要修改StartupRunner.java文件,代碼如下:

package org.test.bookpub;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;

import javax.sql.DataSource;

public class StartupRunner implements CommandLineRunner {
    protected static final Logger logger = LoggerFactory.getLogger(StartupRunner.class);

    @Autowired
    private DataSource ds;

    @Override
    public void run(String... strings) throws Exception {
        logger.info("Datasource: " + ds.toString());
    }
}

啟動應用程序,可以看到如下輸出:driverClassName=org.h2.Driver;因此,可以證明,Spring Boot根據我們自動織入DataSource的代碼,自動創建并初始化了一個H2數據庫。不過,這個數據庫并沒什么用,因為存放其中的數據會在系統停止后就丟失。通過修改配置,我們可以將數據存放在磁盤上。關于H2數據庫的配置文件如下:

spring.datasource.url = jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username = sa
spring.datasource.password =

然后啟動應用程序,并檢查你的home目錄下是否存在test.mv.db文件。通過“~/test”,就告訴Spring Boot,H2數據庫的數據會存放在test.mv.db這個文件中。

綜上,可以看出,Spring Boot試圖通過spring.datasource分組下的一系列配置項來簡化用戶對數據庫的使用,我們經常使用的配置項有:url,username,password以及driver-class-name等等。PS:driverClassName或者driver-class-name都可以,Spring Boot會在內部進行統一處理。

最常用的開源數據庫是Mysql,在Spring Boot通過下列配置項來配置mysql:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springbootcookbook
spring.datasource.username=root
spring.datasource.password=

如果希望通過Hibernate依靠Entity類自動創建數據庫和數據表,則還需要加上配置項—— spring.jpa.hibernate.ddl-auto=create-drop 。PS:在生產環境中不要使用create-drop,這樣會在程序啟動時先刪除舊的,再自動創建新的,最好使用update;還可以通過設置 spring.jpa.show-sql = true 來顯示自動創建表的SQL語句,通過 spring.jpa.database = MYSQL 指定具體的數據,如果不明確指定Spring boot會根據classpath中的依賴項自動配置。

在Spring項目中,如果數據量比較簡單,我們可以考慮使用JdbcTemplate,而不是直接定義Datasource,配置jdbc的代碼如下:

@Autowired
private JdbcTemplate jdbcTemplate;

只要定義了上面這個代碼,Spring Boot會自動創建一個Datasource對象,然后再創建一個jdbctemplate對象來管理datasource,通過jdbctemplate操作數據庫可以減少大量模板代碼。如果你對SpringBoot的原理感興趣,可以在org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration類中查看其具體實現。

2.創建數據倉庫服務(data repository service)

連接數據庫并直接執行SQL語句這種思路非常古老,早在很多年前就已經出現了ORM(Object Relational Mapping)框架來簡化這部分工作,最有名的是Hibernate,但是現在更火的好像是Mybatis。關于spring boot和Mybatis的整合,可以參考: mybatis-spring-boot 。我們這里使用Hibernate進行演示。我們將會增加一些實體類,這些實體類決定了數據庫的表結構,還要定義一個CrudRepository接口,用于操作數據。

示例程序是一個圖書管理系統,顯然,數據庫中應該具備以下領域對象(domain object):Book、Author、Reviewrs以及Publisher。首先在src/main/java/org/test/bookpub下建立包domain,然后再在這個包下建立相應的實體類。具體代碼列舉如下(為了節省空間,省去了getter和setter):

  • Book.java
package com.test.bookpub.domain;

import javax.persistence.*;
import java.util.List;

@Entity
public class Book {
    @Id
    @GeneratedValue
    private Long id;
    private String isbn;
    private String title;
    private String description;

    @ManyToOne
    private Author author;
    @ManyToOne
    private Publisher publisher;

    @ManyToMany
    private List reviewers;

    protected Book() { }

    public Book(Author author, String isbn, Publisher publisher, String title) {
        this.author = author;
        this.isbn = isbn;
        this.publisher = publisher;
        this.title = title;
    }
}
  • Author.java
package com.test.bookpub.domain;

import javax.persistence.*;
import java.util.List;

@Entity
public class Author {
    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String lastName;
    @OneToMany(mappedBy = "author")
    private List books;

    protected Author() {

    }

    public Author(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
  • Publisher.java
package com.test.bookpub.domain;

import javax.persistence.*;
import java.util.List;

@Entity
public class Publisher {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

    @OneToMany(mappedBy = "publisher")
    private List books;

    protected Publisher() { }

    public Publisher(String name) {
        this.name = name;
    }

    @Entity
    public class Reviewer {
        @Id
        @GeneratedValue
        private Long id;
        private String firstName;
        private String lastName;

        protected Reviewer() { }

        public Reviewer(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }
}
  • repository層:創建完實體類,還需要創建BookRepository接口,該接口繼承自CrudRepository,這個接口放在src/main/java/com/test/bookpub/repository包中,具體代碼如下:
package com.test.bookpub.repository;

import com.test.bookpub.domain.Book;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BookRepository extends CrudRepository {
    Book findBookByIsbn(String isbn);
}
  • 織入BookRepository,最后需要再StartupRunner中定義BookRepository對象,并自動織入。
package com.test.bookpub;

import com.test.bookpub.repository.BookRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;

public class StartupRunner implements CommandLineRunner {
    protected final Logger logger = LoggerFactory.getLogger(StartupRunner.class);

    @Autowired
    private BookRepository bookRepository;

    @Override
    public void run(String... strings) throws Exception {
        logger.info("Number of books: " + bookRepository.count());
    }
}

可能讀者朋友你也注意到了,到此為止,我們都沒有寫一行SQL語句,也沒有在代碼中涉及到數據庫連接、建立查詢等方面的內容。只有實體類上的各種注解表明我們在于數據庫做交互:@Entity,@Repository,@Id,@GeneratedValue,@ManyToOne,@ManyToMany以及@OneToMany,這些注解屬于Java Persistance API。我們通過CrudRespository接口的子接口與數據庫交互,同時由Spring建立對象與數據庫表、數據庫表中的數據之間的映射關系。下面依次說明這些注解的含義和使用:

  • @Entity,說明被這個注解修飾的類應該與一張數據庫表相對應,表的名稱可以由類名推斷,當然了,也可以明確配置,只要加上 @Table(name = "books") 即可。需要特別注意,每個Entity類都應該有一個protected訪問級別的無參構造函數,用于給Hibernate提供初始化的入口。
  • @Id and @GeneratedValue:@Id注解修飾的屬性應該作為表中的主鍵處理、@GeneratedValue修飾的屬性應該由數據庫自動生成,而不需要明確指定。
  • @ManyToOne, @ManyToMany表明具體的數據存放在其他表中,在這個例子里,書和作者是多對一的關系,書和出版社是多對一的關系,因此book表中的author和publisher相當于數據表中的外鍵;并且在Publisher中通過@OneToMany(mapped = “publisher”)定義一個反向關聯(1——>n),表明book類中的publisher屬性與這里的books形成對應關系。
  • @Repository 用來表示訪問數據庫并操作數據的接口,同時它修飾的接口也可以被component scan機制探測到并注冊為bean,這樣就可以在其他模塊中通過@Autowired織入。
  • CrudRepository,直接查看源代碼,CrudRepository的代碼如下:
public interface CrudRepository
    extends Repository {

     S save(S entity); //保存給定的entity

    T findOne(ID primaryKey);//根據給定的id查詢對應的entity

    Iterable findAll(); //查詢所有entity          

    Long count();//返回entity的個數

    void delete(T entity); //刪除給定的entity   

    boolean exists(ID primaryKey); //判斷給定id的entity是否存在

    // … more functionality omitted.
}

我們可以添加自定義的接口函數,JPA會提供對應的SQL查詢,例如,在本例中的BookRepository中可以增加findBookByIsbn(String isbn)函數,JPA會自動創建對應的SQL查詢——根據isbn查詢圖書,這種將方法名轉換為SQL語句的機制十分方便且功能強大,例如你可以增加類似findByNameIgnoringCase(String name)這種復雜查詢。

最后,我們利用 mvn spring-boot:run 運行應用程序,觀察下Hibernate是如何建立數據庫連接,如何檢測數據表是否存在以及如何自動創建表的過程。

spring with mysql

3. 參考資料

來自: http://blog.jobbole.com/97235/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!