在如今的關系型數據庫中,有兩個開源產品是你必須知道的。其中一個是MySQL,相信關注我的小伙伴們一定都不陌生,因為之前的Spring Boot關于關系型數據庫的所有例子都是對MySQL來介紹的。而今天我們將介紹另外一個開源關系型數據庫:PostgreSQL,以及在Spring Boot中如何使用。
PostgreSQL簡介
在學習PostgreSQL的時候,我們總是會將其與MySQL放一起來比較:MySQL自稱是最流行的開源數據庫,而PostgreSQL則標榜自己是最先進的開源數據庫,那么有多先進呢?下面就一起認識一下它!
PostgreSQL是一種特性非常齊全的自由軟件的對象-關系型數據庫管理系統(ORDBMS),是以加州大學計算機系開發的POSTGRES,4.2版本為基礎的對象關系型數據庫管理系統。POSTGRES的許多領先概念只是在比較遲的時候才出現在商業網站數據庫中。PostgreSQL支持大部分的SQL標準并且提供了很多其他現代特性,如復雜查詢、外鍵、觸發器、視圖、事務完整性、多版本并發控制等。同樣,PostgreSQL也可以用許多方法擴展,例如通過增加新的數據類型、函數、操作符、聚集函數、索引方法、過程語言等。另外,因為許可證的靈活,任何人都可以以任何目的免費使用、修改和分發PostgreSQL。
PostgreSQL的優勢
既然跟MySQL一樣,同為關系型數據庫,那么什么時候用MySQL,什么時候用PostgreSQL自然是我們需要去了解的。所以下面簡單介紹一下,PostgreSQL相比于MySQL來說,都有哪些優勢,如果你有這些需求,那么選擇PostgreSQL就優于MySQL,反之則還是選擇MySQL更佳:
- 支持存儲一些特殊的數據類型,比如:array、json、jsonb
- 對地理信息的存儲與處理有更好的支持,所以它可以成為一個空間數據庫,更好的管理數據測量和幾何拓撲分析
- 可以快速構建REST API,通過PostgREST可以方便的為任何PostgreSQL數據庫提供RESTful API的服務
- 支持樹狀結構,可以更方便的處理具備此類特性的數據存儲
- 外部數據源支持,可以把MySQL、Oracle、CSV、Hadoop等當成自己數據庫中的表來進行查詢
- 對索引的支持更強,PostgreSQL支持 B-樹、哈希、R-樹和 Gist 索引。而MySQL取決于存儲引擎。MyISAM:BTREE,InnoDB:BTREE。
- 事務隔離更好,MySQL 的事務隔離級別repeatable read并不能阻止常見的并發更新,得加鎖才可以,但悲觀鎖會影響性能,手動實現樂觀鎖又復雜。而 PostgreSQL 的列里有隱藏的樂觀鎖 version 字段,默認的 repeatable read 級別就能保證并發更新的正確性,并且又有樂觀鎖的性能。
- 時間精度更高,可以精確到秒以下
- 字符支持更好,MySQL里需要utf8mb4才能顯示emoji,PostgreSQL沒這個坑
- 存儲方式支持更大的數據量,PostgreSQL主表采用堆表存放,MySQL采用索引組織表,能夠支持比MySQL更大的數據量。
- 序列支持更好,MySQL不支持多個表從同一個序列中取id,而PostgreSQL可以
- 增加列更簡單,MySQL表增加列,基本上是重建表和索引,會花很長時間。PostgreSQL表增加列,只是在數據字典中增加表定義,不會重建表。
這里僅列舉了開發者視角關注的一些優勢,還有一些其他優勢讀者可查看這篇文章,獲得更詳細的解讀。
下載與安裝
讀者可以通過下面的鏈接獲取PostgreSQL各版本的安裝程序,這里不對安裝過程做詳細描述了,根據安裝程序的指引相信大家都能完成安裝(一路next,設置訪問密碼和端口即可)。
安裝完成后,打開pgAdmin。因為自帶了界面化的管理工具,所以如果你用過mysql等任何關系型數據庫的話,基本不用怎么學,就可以上手使用了。
Spring Boot中如何使用
在安裝好了PostgreSQL之后,下面我們嘗試一下在Spring Boot中使用PostgreSQL數據庫。
第一步:創建一個基礎的Spring Boot項目(如果您還不會,可以參考這篇文章:快速入門)
第二步:在pom.xml中引入訪問PostgreSQL需要的兩個重要依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
這里postgresql是必須的,
spring-boot-starter-data-jpa的還可以替換成其他的數據訪問封裝框架,比如:MyBatis等,具體根據你使用習慣來替換依賴即可。因為已經是更上層的封裝,所以基本使用與之前用MySQL是類似的,所以你也可以參考之前MySQL的文章進行配置,但數據源部分需要根據下面的部分配置。
第三步:在配置文件中為PostgreSQL數據庫配置數據源、以及JPA的必要配置。
spring:
datasource:
url: jdbc:postgresql://localhost:5432/test
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
hbm2ddl:
auto: create
第四步:創建用戶信息實體,映射user_info表(最后完成可在pgAdmin中查看)
@Entity
@Data
@NoArgsConstructor
public class UserInfo {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer age;
public UserInfo(String name, Integer age) {
this.name = name;
this.age = age;
}
}
第五步:創建用戶信息實體的增刪改查
public interface UserInfoRepository extends JpaRepository<UserInfo, Long> {
UserInfo findByName(String name);
UserInfo findByNameAndAge(String name, Integer age);
@Query("from UserInfo u where u.name=:name")
UserInfo findUser(@Param("name") String name);
}
第六步:創建單元測試,嘗試一下增刪改查操作。
@Slf4j
@SpringBootTest
public class ApplicationTests {
@Autowired
private UserInfoRepository userRepository;
@Test
public void test() throws Exception {
// 創建10條記錄
userRepository.save(new UserInfo("AAA", 10));
userRepository.save(new UserInfo("BBB", 20));
userRepository.save(new UserInfo("CCC", 30));
userRepository.save(new UserInfo("DDD", 40));
userRepository.save(new UserInfo("EEE", 50));
userRepository.save(new UserInfo("FFF", 60));
userRepository.save(new UserInfo("GGG", 70));
userRepository.save(new UserInfo("HHH", 80));
userRepository.save(new UserInfo("III", 90));
userRepository.save(new UserInfo("JJJ", 100));
// 測試findAll, 查詢所有記錄
Assertions.assertEquals(10, userRepository.findAll().size());
// 測試findByName, 查詢姓名為FFF的User
Assertions.assertEquals(60, userRepository.findByName("FFF").getAge().longValue());
// 測試findUser, 查詢姓名為FFF的User
Assertions.assertEquals(60, userRepository.findUser("FFF").getAge().longValue());
// 測試findByNameAndAge, 查詢姓名為FFF并且年齡為60的User
Assertions.assertEquals("FFF", userRepository.findByNameAndAge("FFF", 60).getName());
// 測試刪除姓名為AAA的User
userRepository.delete(userRepository.findByName("AAA"));
// 測試findAll, 查詢所有記錄, 驗證上面的刪除是否成功
Assertions.assertEquals(9, userRepository.findAll().size());
}
}
把單元測試跑起來:
一切順利的話,因為這里用的是create策略,所以表還在,打開pgAdmin,可以看到user_info表自動創建出來了,里面的數據也可以查到,看看跟單元測試的邏輯是否符合。
思考一下
如果您之前有讀過本系列教程中關于MySQL的10多篇使用案例,再看這篇使用PostgreSQL的案例,是不是感覺差別非常小?其實真正變動的部分主要是兩個地方:
- 數據庫驅動的依賴
- 數據源的配置信息
而對于更為上層的數據操作,其實并沒有太大的變化,尤其是當使用Spring Data JPA的時候,這就是抽象的魅力所在!你體會到了嗎?