02.18 使用Spring Boot 2.0+ Spring data JPA+ PostgreSQL構建一個項目

微服務作為Java技術圈最火的技術架構,所以核心SpringBoot作為最基礎單元值得我們好好研究。

PG作為數據庫圈最全面的數據庫,有著全站型數據庫之稱。

在下面這篇文章中,我將介紹如何使用SpringBoot2.0+SpringDataJPA+PostgreSQL構建一個。

我們將使用到如下技術和工具:


  • Spring Boot 2.1.2.RELEASE
  • Spring 5.1.4.RELEASE
  • Hibernate 5.3.7
  • HikariCP 3.2.0
  • H2 in-memory database 1.4.197
  • PostgreSQL driver 42.2.5
  • Maven 3
  • Java 8
  • 首先我們創建一個SpringBoot+SpringDataJPA(先使用H2內存數據庫構建)


    使用Spring Boot 2.0+ Spring data JPA+ PostgreSQL構建一個項目


    1.項目目錄


    使用Spring Boot 2.0+ Spring data JPA+ PostgreSQL構建一個項目

    2. Maven構建

    pom.xml 文件中的依賴

    <code>
    <project> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    \t\t http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0/<modelversion>

    <artifactid>spring-data-jpa/<artifactid>
    <packaging>jar/<packaging>
    <name>Spring Boot Spring Data JPA/<name>
    <version>1.0/<version>

    <parent>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-parent/<artifactid>
    <version>2.1.2.RELEASE/<version>
    /<parent>

    <properties>
    <java.version>1.8/<java.version>
    <downloadsources>true/<downloadsources>
    <downloadjavadocs>true/<downloadjavadocs>
    /<properties>

    <dependencies>


    <dependency>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-data-jpa/<artifactid>
    /<dependency>


    <dependency>
    <groupid>com.h2database/<groupid>
    <artifactid>h2/<artifactid>
    /<dependency>

    <dependency>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-test/<artifactid>
    <scope>test/<scope>

    /<dependency>

    /<dependencies>

    <build>
    <plugins>

    <plugin>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-maven-plugin/<artifactid>
    /<plugin>

    <plugin>
    <groupid>org.apache.maven.plugins/<groupid>
    <artifactid>maven-surefire-plugin/<artifactid>
    <version>2.22.0/<version>
    /<plugin>

    /<plugins>

    /<build>
    /<project>/<code>

    3. 構建Spring Data JPA

    Book.java

    <code>package com.mkyong;

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

    @Entity
    public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    public Book() {
    }

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

    //getters, setters, toString...

    }
    複製/<code>

    BookRepository.java

    <code>package com.mkyong;

    import org.springframework.data.repository.CrudRepository;

    import java.util.List;

    public interface BookRepository extends CrudRepository<book> {

    List<book> findByName(String name);
    /<book>/<book>/<code>


    4. @SpringBootApplication啟動

    4.1啟動Spring Boot,將3本書插入H2數據庫,然後測試該find()方法。

    StartApplication.java

    <code>package com.mkyong;

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

    @SpringBootApplication
    public class StartApplication implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(StartApplication.class);

    @Autowired
    private BookRepository repository;

    public static void main(String[] args) {
    SpringApplication.run(StartApplication.class, args);
    }

    @Override
    public void run(String... args) {

    log.info("StartApplication...");


    repository.save(new Book("Java"));
    repository.save(new Book("Node"));
    repository.save(new Book("Python"));

    System.out.println("\\nfindAll()");
    repository.findAll().forEach(x -> System.out.println(x));

    System.out.println("\\nfindById(1L)");
    repository.findById(1l).ifPresent(x -> System.out.println(x));

    System.out.println("\\nfindByName('Node')");
    repository.findByName("Node").forEach(x -> System.out.println(x));

    }

    }/<code>

    5. 使用HikariCP連接池

    默認情況下,Spring Boot 2使用HikariCP作為默認連接池。

    5.1啟用com.zaxxer調試的日誌記錄級別,它將打印出默認的HikariCP配置。

    application.properties

    <code>logging.level.org.springframework=INFO
    logging.level.com.mkyong=INFO
    logging.level.com.zaxxer=DEBUG
    logging.level.root=ERROR/<code>

    5.2運行Spring Boot,查看日誌:

    <code>DEBUG com.zaxxer.hikari.HikariConfig - Driver class org.h2.Driver found in Thread context class loader jdk.internal.loader.ClassLoaders$AppClassLoader@28c97a5
    DEBUG com.zaxxer.hikari.HikariConfig - HikariPool-1 - configuration:
    DEBUG com.zaxxer.hikari.HikariConfig - allowPoolSuspension.............false
    DEBUG com.zaxxer.hikari.HikariConfig - autoCommit......................true
    DEBUG com.zaxxer.hikari.HikariConfig - catalog.........................none
    DEBUG com.zaxxer.hikari.HikariConfig - connectionInitSql...............none
    DEBUG com.zaxxer.hikari.HikariConfig - connectionTestQuery.............none
    DEBUG com.zaxxer.hikari.HikariConfig - connectionTimeout...............30000
    DEBUG com.zaxxer.hikari.HikariConfig - dataSource......................none
    DEBUG com.zaxxer.hikari.HikariConfig - dataSourceClassName.............none
    DEBUG com.zaxxer.hikari.HikariConfig - dataSourceJNDI..................none
    DEBUG com.zaxxer.hikari.HikariConfig - dataSourceProperties............{password=<masked>}

    DEBUG com.zaxxer.hikari.HikariConfig - driverClassName................."org.h2.Driver"
    DEBUG com.zaxxer.hikari.HikariConfig - healthCheckProperties...........{}
    DEBUG com.zaxxer.hikari.HikariConfig - healthCheckRegistry.............none
    DEBUG com.zaxxer.hikari.HikariConfig - idleTimeout.....................600000
    DEBUG com.zaxxer.hikari.HikariConfig - initializationFailTimeout.......1
    DEBUG com.zaxxer.hikari.HikariConfig - isolateInternalQueries..........false
    DEBUG com.zaxxer.hikari.HikariConfig - jdbcUrl.........................jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    DEBUG com.zaxxer.hikari.HikariConfig - leakDetectionThreshold..........0
    DEBUG com.zaxxer.hikari.HikariConfig - maxLifetime.....................1800000
    DEBUG com.zaxxer.hikari.HikariConfig - maximumPoolSize.................10
    DEBUG com.zaxxer.hikari.HikariConfig - metricRegistry..................none
    DEBUG com.zaxxer.hikari.HikariConfig - metricsTrackerFactory...........none
    DEBUG com.zaxxer.hikari.HikariConfig - minimumIdle.....................10
    DEBUG com.zaxxer.hikari.HikariConfig - password........................<masked>
    DEBUG com.zaxxer.hikari.HikariConfig - poolName........................"HikariPool-1"
    DEBUG com.zaxxer.hikari.HikariConfig - readOnly........................false
    DEBUG com.zaxxer.hikari.HikariConfig - registerMbeans..................false
    DEBUG com.zaxxer.hikari.HikariConfig - scheduledExecutor...............none
    DEBUG com.zaxxer.hikari.HikariConfig - schema..........................none
    DEBUG com.zaxxer.hikari.HikariConfig - threadFactory...................internal
    DEBUG com.zaxxer.hikari.HikariConfig - transactionIsolation............default
    DEBUG com.zaxxer.hikari.HikariConfig - username........................"sa"
    DEBUG com.zaxxer.hikari.HikariConfig - validationTimeout...............5000
    INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
    INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=1, active=0, idle=1, waiting=0)
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn1: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn2: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn3: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn4: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn5: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn6: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn7: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn8: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn9: url=jdbc:h2:mem:testdb user=SA
    DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - After adding stats (total=10, active=0, idle=10, waiting=0)
    複製/<masked>/<masked>/<code>

    5.2我們可以使用spring.datasource.hikari.*覆蓋默認設置。

    application.properties

    <code>logging.level.org.springframework=INFO
    logging.level.com.mkyong=INFO
    logging.level.com.zaxxer=DEBUG
    logging.level.root=ERROR

    spring.datasource.hikari.connectionTimeout=20000

    spring.datasource.hikari.maximumPoolSize=5
    spring.datasource.hikari.poolName=HikariPoolZZZ
    複製/<code>

    6.單元測試

    6.1 @DataJpaTest並TestEntityManager測試一個Spring數據JPA存儲庫。

    BookRepositoryTest.java

    <code>package com.mkyong;

    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
    import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
    import org.springframework.test.context.junit4.SpringRunner;

    import java.util.List;

    import static org.assertj.core.api.Assertions.assertThat;
    import static org.junit.Assert.assertEquals;

    @RunWith(SpringRunner.class)
    @DataJpaTest
    public class BookRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private BookRepository repository;

    @Test
    public void testFindByName() {

    entityManager.persist(new Book("C++"));

    List<book> books = repository.findByName("C++");
    assertEquals(1, books.size());

    assertThat(books).extracting(Book::getName).containsOnly("C++");

    }

    }
    複製/<book>/<code>

    7.演示

    <code>$ mvn spring-boot:run

    INFO com.mkyong.StartApplication - Started StartApplication in 2.79 seconds (JVM running for 10.883)
    INFO com.mkyong.StartApplication - StartApplication...

    findAll()
    DEBUG com.zaxxer.hikari.pool.PoolBase - HikariPoolZZZ - Reset (readOnly) on connection conn0: url=jdbc:h2:mem:testdb user=SA
    Book{id=1, name='Java'}
    Book{id=2, name='Node'}
    Book{id=3, name='Python'}

    findById(1L)
    DEBUG com.zaxxer.hikari.pool.PoolBase - HikariPoolZZZ - Reset (readOnly) on connection conn0: url=jdbc:h2:mem:testdb user=SA
    Book{id=1, name='Java'}

    findByName('Node')
    Book{id=2, name='Node'}/<code>

    到這裡構建一個SpringBoot+SpringDataJPA的框架已經完成,但是這裡使用的H2內存數據庫,下面我們要將H2數據庫轉換成PostgreSQL數據庫。


    使用Spring Boot 2.0+ Spring data JPA+ PostgreSQL構建一個項目


    pom.xml修改添加

    <code>\t<dependency>
    \t\t<groupid>org.postgresql/<groupid>
    \t\t<artifactid>postgresql/<artifactid>
    \t/<dependency>/<code>

    1. Maven

    pom.xml

    <code>
    <project> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    \t\t http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0/<modelversion>

    <artifactid>spring-boot-data-jpa/<artifactid>
    <packaging>jar/<packaging>
    <name>Spring Boot Spring Data JPA/<name>
    <version>1.0/<version>

    <parent>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-parent/<artifactid>
    <version>2.1.2.RELEASE/<version>
    /<parent>

    <properties>
    <java.version>1.8/<java.version>
    <downloadsources>true/<downloadsources>
    <downloadjavadocs>true/<downloadjavadocs>
    /<properties>

    <dependencies>


    <dependency>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-data-jpa/<artifactid>
    /<dependency>


    <dependency>
    <groupid>org.postgresql/<groupid>
    <artifactid>postgresql/<artifactid>
    /<dependency>

    <dependency>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-starter-test/<artifactid>
    <scope>test/<scope>
    /<dependency>

    /<dependencies>

    <build>
    <plugins>

    <plugin>
    <groupid>org.springframework.boot/<groupid>
    <artifactid>spring-boot-maven-plugin/<artifactid>
    /<plugin>

    <plugin>
    <groupid>org.apache.maven.plugins/<groupid>
    <artifactid>maven-surefire-plugin/<artifactid>
    <version>2.22.0/<version>
    /<plugin>

    /<plugins>

    /<build>
    /<project>/<code>

    2. 配置 PostgreSQL數據庫

    application.properties

    <code>## default connection pool
    spring.datasource.hikari.connectionTimeout=20000
    spring.datasource.hikari.maximumPoolSize=5

    ## PostgreSQL
    spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
    spring.datasource.username=postgres
    spring.datasource.password=password

    #drop n create table again, good for testing, comment this in production
    spring.jpa.hibernate.ddl-auto=create/<code>

    最後 源碼下載地址:

    https://github.com/mkyong/spring-boot.git


    分享到:


    相關文章: